为什么instanceof在Babel-node下的Error子类的实例上工作? [英] Why doesn't instanceof work on instances of Error subclasses under babel-node?

查看:129
本文介绍了为什么instanceof在Babel-node下的Error子类的实例上工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到 instanceof 操作符在错误子类的实例上不起作用,在操作系统X上的href =https://babeljs.io/docs/usage/cli/#babel-node =noreferrer> babel-node 版本6.1.18 /节点版本5.1.0。为什么是这样?相同的代码在浏览器中运行良好,请尝试以小提琴为例。

I am seeing that the instanceof operator doesn't work on instances of Error subclasses, when running under babel-node version 6.1.18/Node version 5.1.0 on OS X. Why is this? The same code works well in the browser, try my fiddle for an example.

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

The following code outputs true in the browser, whereas under babel-node it's 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 适用于其他基类,而不是错误

I can only imagine this being due to a bug in babel-node, since instanceof works for other base classes than Error.

{
  "presets": ["es2015"]
}



编译输出



这是由babel编译的JavaScript 6.1.18:

Compiled Output

This is the JavaScript compiled by babel 6.1.18:

'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

tl;dr If you're on Babel 6, you can use https://www.npmjs.com/package/babel-plugin-transform-builtin-extend

扩展内置类型,如 Array 错误等等,从未在Babel中得到支持。它在真正的ES6环境中是完全有效的,但是有一些要求使得它能够以与旧版浏览器兼容的方式变得非常困难。它在Babel 5中工作,因为它没有抛出错误,但是从扩展子类中实例化的对象不像原来的那样工作,例如:

Extending builtin types like Array and Error and such has never been supported in Babel. It is perfectly valid in a real ES6 environment, but there are requirements to make it work that are very difficult to transpile in a way that is compatible with older browsers. It "worked" in Babel 5 in that it didn't throw an error, but objects instantiated from the extended subclass did not work like they were supposed to, for example:

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 ,它的行为有点像一个数组,并且有数组方法,但它并没有完全像一个数组。

While it did not error out, the subclass does not properly get a 'stack' like errors are supposed to. Similarly, if you were to extend Array it might behave somewhat like an array, and have array methods, but it did not behave fully like an array.

Babel 5文档特别将此作为课程的一个边缘案例来注意。

The Babel 5 documentation specifically called this out as an edge-case of classes to be aware of.

在Babel 6中,课程是在如何处理子类化方面更改为更具规范性,而副作用就是现在上述代码仍然不能正常工作,但它不会以与以前不同的方式工作。这已经在 https://phabricator.babeljs.io/T3083 中介绍过,但我将详细介绍一个潜在的解决方案。

In Babel 6, classes were changed to be more spec-compliant in how subclassing is handled, and a side-effect of that is that now the above code will still not work, but it will not work in a different way than before. This has been covered in https://phabricator.babeljs.io/T3083, but I'll elaborate here on a potential solution.

要返回Babel 5子类行为(其中记住,仍然不正确或推荐),您可以将内置构造函数包装在您自己的临时类中,例如

To return Babel 5 subclassing behavior (which remember, is still not right or recommended), you can wrap the builtin constructor in your own temporary class, e.g.

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

    return ExtendableBuiltin;
}

有了这个帮手,而不是做

With this helper, rather than doing

class MyError extends Error {}

do

class MyError extends ExtendableBuiltin(Error) {}

然而,在具体情况下,您已经说过您在Node 5.x上。节点5支持本机ES6类而不进行泛化。我建议您通过删除 es2015 预设,而使用 node5 ,所以你得到本地类,除其他外。在这种情况下,

In your specific case however, you have said that you are on Node 5.x. Node 5 has support for native ES6 classes without transpiling. I'd recommend you use those by dropping the es2015 preset and instead using node5 so you get native classes, among other things. In that context,

class MyError extends Error {}

将按照您的期望工作。

对于不在节点4/5或最近只有Chrome的用户可能会考虑使用 https://www.npmjs.com/package/error 等内容。您还可以浏览 https://www.npmjs.com/package/babel-plugin-transform-内置-延伸近似选项是与Babel 5相同的行为。请注意,非近似行为绝对是边缘化的, 100%的案例可能无法工作。

For people not on Node 4/5, or recent Chrome only, you may want to consider using something like https://www.npmjs.com/package/error. You can also explore https://www.npmjs.com/package/babel-plugin-transform-builtin-extend. The approximate option from that is the same behavior from Babel 5. Beware that the non-approximate behavior is definitely edge-casey and may not work in 100% of cases.

这篇关于为什么instanceof在Babel-node下的Error子类的实例上工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆