为什么没有instanceof在babel-node下的Error子类的实例上工作?

我看到在OS X上运行babel-node版本6.1.18 /节点版本5.1.0时, instanceof运算符不能运行在Error子类的实例上。为什么? 相同的代码在浏览器中运行良好,请尝试我的小提琴示例。

下面的代码在浏览器中输出true ,而在babel-node下则为false:

 class Sub extends Error { } let s = new Sub() console.log(`The variable 's' is an instance of Sub: ${s instanceof Sub}`) 

我只能想象这是由于babel-node中的错误,因为instanceof对于其他基类的工作比Error

.babelrc

 { "presets": ["es2015"] } 

编译输出

这是由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; dr如果你在Babel 6上,你可以使用https://www.npmjs.com/package/babel-plugin-transform-b​​uiltin-extend

ArrayError这样的扩展内buildtypes在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它可能会像数组一样,并有数组方法,但它不像数组一样。

Babel 5文件明确地将此作为需要注意的类的边缘案例。

在Babel 6中,类被更改为在处理子类方面更符合spec规范,并且副作用是现在上面的代码仍然不起作用,但是它不会以与以前不同的方式工作。 这已经在https://phabricator.babeljs.io/T3083中进行了介绍,但是我会在这里详细介绍一个潜在的解决scheme。

为了返回Babel 5的子类行为(记住,仍然是不正确的或推荐的),你可以把内build构造函数包装在你自己的临时类中,例如

 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 {} 

 class MyError extends ExtendableBuiltin(Error) {} 

然而在你的具体情况下,你说你在Node 5.x上。 节点5支持本地ES6类,而无需转发。 我build议你通过放弃es2015预置来使用这些预置,而使用node5这样你就可以获得本地的课程。 在这方面,

 class MyError extends Error {} 

将按照您的期望工作。

对于不在Node 4/5或最近的Chrome上的用户,您可能需要考虑使用类似https://www.npmjs.com/package/error的内容 。 您也可以浏览https://www.npmjs.com/package/babel-plugin-transform-b​​uiltin-extend 。 从这个approximate选项是从巴别尔5相同的行为。请注意,非approximate行为肯定是边缘性,可能无法在100%的情况下工作。