在OS X上运行babel-node个版本6.1.18/Node版本5.1.0时,我发现instanceof操作符无法处理Error个子类的实例.这是为什么?同样的代码在浏览器中运行良好,请以my fiddle为例.

以下代码在浏览器中输出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 中的一个bug造成的,因为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;博士如果你在Babel 6上你可以用https://www.npmjs.com/package/babel-plugin-transform-builtin-extend

Babel从未支持扩展内置类型,如ArrayError等.它在真正的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文档特别将其称为需要注意的类的边缘 case .

在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类,无需传输.我建议你go 掉es2015预设,改为使用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行为肯定是edge casey,可能在https://www.npmjs.com/package/error%的情况下都不起作用.

Node.js相关问答推荐

postgresql层与应用层的序列化

express返回意外的URL

如何使用NodeJS处理来自请求的单个或多个文件?

如果非SQL函数在事务内部运行失败,PG-Promise事务会回滚吗?

我的Node.js应用程序没有将Mongoose方法findByIdAndDelete作为函数进行检测

如何使用mongoose引用不在项目中的模型

我如何保护nodejs中的路由

错误:0308010C:try 通过 Github 推送部署到 firebase 托管时出现数字

为什么它无法发送发布请求并更改为 chrome 中的获取方法?

结合后端(Express)和前端(Angular)路由

如何使用 node.js 将两个或多个 API 请求组合成一个端点并表达

多字段传递获取查询失败

将已保存的卡片从条带显示到前端

后端位于 Docker 容器中时的 SvelteKit SSR fetch()

Node JS:自动 Select `http.get`与`https.get`

Heroku + Node:找不到模块错误

如何让 Mocha 加载定义全局挂钩或实用程序的 helper.js 文件?

如何从 find 方法返回 Mongoose 结果?

如何在 node.js 沙箱中安全地运行用户提交的脚本?

大型项目的 NodeJS vs Play 框架