akn*_*ds1 73 javascript node.js ecmascript-6 babeljs
我看到instanceof操作符在OS X上的babel-node版本6.1.18/Node版本5.1.0 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}`)
Run Code Online (Sandbox Code Playgroud)
我只能想象这是由于babel-node中的一个bug,因为它instanceof适用于其他基类Error.
{
"presets": ["es2015"]
}
Run Code Online (Sandbox Code Playgroud)
这是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));
Run Code Online (Sandbox Code Playgroud)
log*_*yth 87
tl; dr如果您使用的是Babel 6,则可以使用https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
扩展内置类型,如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);
Run Code Online (Sandbox Code Playgroud)
结果是
e1 false
e2 true
Run Code Online (Sandbox Code Playgroud)
虽然它没有错误输出,但是子类没有像错误一样正确地获得"堆栈".类似地,如果你要扩展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;
}
Run Code Online (Sandbox Code Playgroud)
有了这个助手,而不是做
class MyError extends Error {}
Run Code Online (Sandbox Code Playgroud)
做
class MyError extends ExtendableBuiltin(Error) {}
Run Code Online (Sandbox Code Playgroud)
但是,在您的具体情况下,您已经说过您使用的是Node 5.x. 节点5支持本机ES6类而无需转换.我建议您通过删除es2015预设来使用它们,而不是使用它,node5以便您获得本机类,以及其他内容.在这方面,
class MyError extends Error {}
Run Code Online (Sandbox Code Playgroud)
将以你期望的方式工作.
对于不在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%的情况下可能无效.
| 归档时间: |
|
| 查看次数: |
14886 次 |
| 最近记录: |