Javascript 为什么';在babel节点下错误子类的实例上工作的t instanceof?

Javascript 为什么';在babel节点下错误子类的实例上工作的t instanceof?,javascript,node.js,ecmascript-6,babeljs,Javascript,Node.js,Ecmascript 6,Babeljs,我发现在OS X上运行6.1.18版/Node 5.1.0版时,instanceof操作符不能处理Error子类的实例。这是为什么?相同的代码在浏览器中运行良好,请以my为例 以下代码在浏览器中输出true,而在babel节点下为false: class Sub extends Error { } let s = new Sub() console.log(`The variable 's' is an instance of Sub: ${s instanceof Sub}`) 我只能想象

我发现在OS X上运行6.1.18版/Node 5.1.0版时,
instanceof
操作符不能处理
Error
子类的实例。这是为什么?相同的代码在浏览器中运行良好,请以my为例

以下代码在浏览器中输出
true
,而在babel节点下为false:

class Sub extends Error {
}

let s = new Sub()
console.log(`The variable 's' is an instance of Sub: ${s instanceof Sub}`)
我只能想象这是由于babel节点中的一个bug造成的,因为
instanceof
适用于
Error
以外的其他基类

B.法律改革委员会 编译输出 这是babel 6.1.18编译的JavaScript:

'use strict';

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var Sub = (function (_Error) {
  _inherits(Sub, _Error);

  function Sub() {
    _classCallCheck(this, Sub);

    return _possibleConstructorReturn(this, Object.getPrototypeOf(Sub).apply(this, arguments));
  }

  return Sub;
})(Error);

var s = new Sub();
console.log('The variable \'s\' is an instance of Sub: ' + (s instanceof Sub));

tl;博士如果你在Babel 6上,你可以使用

扩展内置类型,如
Array
Error
,而这类类型在Babel中从未得到支持。它在真正的ES6环境中是完全有效的,但是有一些要求使它能够工作,这些要求很难以与旧浏览器兼容的方式进行传输。它在Babel 5中“起作用”,因为它没有抛出错误,但是从扩展子类实例化的对象没有像预期的那样工作,例如:

class MyError extends Error {}

var e1 = new MyError();
var e2 = new Error();

console.log('e1', 'stack' in e1);
console.log('e2', 'stack' in e2);
导致

e1 false
e2 true
虽然它没有出错,但子类并没有像错误应该得到的那样正确地获得“堆栈”。类似地,如果要扩展
Array
,它的行为可能有点像数组,并且有数组方法,但它的行为并不完全像数组

Babel5文档特别将其称为需要注意的类的边缘案例

在Babel6中,类在子类化的处理方式上被更改为更符合规范,这样做的副作用是,现在上面的代码仍然不能工作,但它的工作方式与以前不同。这已在中介绍,但我将在这里详细介绍一个潜在的解决方案

要返回Babel5子类化行为(记住,它仍然是不正确的或不推荐的),您可以在自己的临时类中封装内置构造函数,例如

function ExtendableBuiltin(cls){
    function ExtendableBuiltin(){
        cls.apply(this, arguments);
    }
    ExtendableBuiltin.prototype = Object.create(cls.prototype);
    Object.setPrototypeOf(ExtendableBuiltin, cls);

    return ExtendableBuiltin;
}
使用此助手,而不是执行

class MyError extends Error {}

但是,在您的特定情况下,您已经说过您在节点5.x上。节点5支持本机ES6类,无需传输。我建议您通过删除
es2015
预设来使用它们,而不是使用so you get native class,以及其他方法。在这方面

class MyError extends Error {}
将按您期望的方式工作


不在节点4/5上的人,或者只是最近的Chrome,你可能想考虑使用类似的东西。你也可以探索。其中的

近似
选项与Babel 5中的行为相同。请注意,非近似行为肯定是边缘casey,在100%的情况下可能不起作用。

instanceof
如果编译目标设置为“es5”,则子类错误将不起作用。我在我的
tsconfig.json中将目标设置为“es6”,并且
instanceof
产生了正确的结果。

我无法重现您的问题。我用在线babel repl和使用babel node(最新版本)进行了测试。您在使用babel时使用了什么预设?也许发布传输的脚本将有助于复制issue@DenysSéguret谢谢,继续检查。@RGraham小提琴在浏览器中使用巴别塔?关键是Babel在浏览器和节点中的工作方式明显不同。@RGraham我已经发布了编译后的脚本。谢谢。那么,创建新异常类的推荐方法是什么呢?毕竟,MDN原型继承
Error
来创建新的异常类。AFAICT,这应该对应于ES6中的子类化,除非我忽略了一些东西。我还发现ES6类语义中有一个子类
Error
的例子。我对我的答案进行了一些扩展。ES6中的子类化比您预期的要复杂得多,并且不能很好地映射到ES5中。它已经修复了吗?还是会被修复?他们在phabricator中为这个问题添加了
Wontfix
标签,这有点令人失望,因为我认为至少如果Babel做得正确并且符合规范,我应该期望这个特性能够工作。对于这些用例,我刚刚在ES5中编写了它们,例如
var CustomError=function(message){Error.call(this,message)this.message=message}
class MyError extends ExtendableBuiltin(Error) {}
class MyError extends Error {}