[英]Why doesn't instanceof work on instances of Error subclasses under babel-node?
我看到在 OS X 上的babel-node版本 6.1.18/Node 版本 5.1.0 下运行时, instanceof
运算符不适用于Error
子类的实例。这是为什么? 相同的代码在浏览器中运行良好,以我的小提琴为例。
以下代码在浏览器中输出为true
,而在 babel-node 下为假:
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 从未支持扩展内置类型,如Array
和Error
等。 它在真实的 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 中,类在子类化的处理方式上被更改为更符合规范,其副作用是现在上面的代码仍然无法工作,但它不会以与以前不同的方式工作。 这已在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。 Node 5 支持原生 ES6 类,无需转译。 我建议您通过删除es2015
预设来使用node5
,而是使用node5
以便您获得本机类等。 在这种情况下,
class MyError extends Error {}
将按照您期望的方式工作。
对于不使用 Node 4/5 或仅使用最新 Chrome 的人,您可能需要考虑使用类似https://www.npmjs.com/package/error 的内容。 您还可以探索https://www.npmjs.com/package/babel-plugin-transform-builtin-extend 。 其中的approximate
选项与 Babel 5 的行为相同。请注意,非approximate
行为绝对是边缘情况,可能无法在 100% 的情况下工作。
如果编译目标设置为“es5”, instanceof
将不适用于子类错误。 我设定的目标为“ES6”在我tsconfig.json
和instanceof
产生正确的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.