我看到在OS X的babel-node版本6.1.18 / Node版本5.1.0 下运行时,该instanceof运算符不适用于Error子类的实例。这是为什么?相同的代码在浏览器中效果很好,请尝试我的小提琴作为示例。
instanceof
Error
以下代码true在浏览器中输出,而在babel-node下为false:
true
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。
{ "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-builtin-extend
Babel从未支持扩展诸如Arrayand Error等这样的内置类型。它在真实的ES6环境中完全有效,但是存在使其难以与旧版浏览器兼容的方式进行转换的要求。它在Babel 5中“起作用”是因为它没有引发错误,但是从扩展子类实例化的对象却无法像预期的那样起作用,例如:
Array
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中,对类进行了更改,使其在处理子类时更加符合规范,其副作用是现在上面的代码 仍然 无法工作,但是将无法以不同于以往的方式工作。这已在https://phabricator.babeljs.io/T3083中进行了介绍,但在此我将详细介绍一个潜在的解决方案。
要返回Babel 5的子类化行为(记住,仍然不正确或不建议这样做),您可以将内置的构造函数包装在自己的临时类中,例如
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类,无需进行编译。我建议您通过删除es2015预设来使用它们,而改用来node5获得本机类,等等。在这种情况下,
es2015
node5
将以您期望的方式工作。
对于不是使用Node 4/5或仅使用最新Chrome的用户,您可能需要考虑使用https://www.npmjs.com/package/error之类的东西。您还可以浏览https://www.npmjs.com/package/babel- plugin-transform-builtin-extend。在approximate从该选项是从巴贝尔相同的行为5.谨防非approximate行为肯定是边缘凯西,不得以的情况下100%的工作。
approximate