instanceof 使用 ES6 class 继承链不起作用
instanceof using ES6 class Inheritance chain doesn't work
使用 ES6 class
语法,我想知道当有多个继承链时,为什么 instanceof
运算符对继承链不起作用?
(optional read)
How instanceof
operator works?
In obj instanceof Constructor
, the instanceof
operator checks if the 'prototype'
property of the Constructor
function is present in the prototype chain of the obj
. If it is present, return true
. Otherwise, false
.
在下面的代码片段中,BTError
继承自 Error
(1.) 和 SomeError
扩展自 BTError
(3.).
但是正如我们从 (4. 中看到的那样,instanceof
运算符结果 false
for new SomeError() instanceof BTError
在我的理解中应该是 true
.
class BTError extends Error {}
console.log('1.', Reflect.getPrototypeOf(BTError.prototype) === Error.prototype); // 1. true
console.log('2.', new BTError() instanceof Error); // 2. true
console.log('');
class SomeError extends BTError {}
console.log('3.', Reflect.getPrototypeOf(SomeError.prototype) === BTError.prototype); // 3. true
console.log('4.', new SomeError() instanceof BTError); // 4. false
console.log('');
class SpecificError extends SomeError {}
console.log('5.', Reflect.getPrototypeOf(SpecificError.prototype) === SomeError.prototype); // 5. true
console.log('6.', new SpecificError() instanceof Error); // 6. true
console.log('7.', new SpecificError() instanceof BTError); // 7. false
console.log('8.', new SpecificError() instanceof SomeError); // 8. false
问题
是否有任何我无法理解的重要事情,或者 instanceof
操作员只是在表现 怪异 ?
关注示例的最后一部分
您正在使用 BabelJS 转换此代码以使其兼容
class BTError extends Error {}
class SomeError extends BTError {}
class SpecificError extends SomeError {}
console.log('6.', new SpecificError() instanceof Error);
console.log('7.', new SpecificError() instanceof BTError);
console.log('8.', new SpecificError() instanceof SomeError);
这是上面代码的转译版本
'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 BTError = function(_Error) {
_inherits(BTError, _Error);
function BTError() {
_classCallCheck(this, BTError);
return _possibleConstructorReturn(this, (BTError.__proto__ || Object.getPrototypeOf(BTError)).apply(this, arguments));
}
return BTError;
}(Error);
var SomeError = function(_BTError) {
_inherits(SomeError, _BTError);
function SomeError() {
_classCallCheck(this, SomeError);
return _possibleConstructorReturn(this, (SomeError.__proto__ || Object.getPrototypeOf(SomeError)).apply(this, arguments));
}
return SomeError;
}(BTError);
var SpecificError = function(_SomeError) {
_inherits(SpecificError, _SomeError);
function SpecificError() {
_classCallCheck(this, SpecificError);
return _possibleConstructorReturn(this, (SpecificError.__proto__ || Object.getPrototypeOf(SpecificError)).apply(this, arguments));
}
return SpecificError;
}(SomeError);
console.log('6.', new SpecificError() instanceof Error); // 6. true
console.log('7.', new SpecificError() instanceof BTError); // 7. false
console.log('8.', new SpecificError() instanceof SomeError); // 8. false
我认为问题出在 _inherit
方法,该方法分配给 subClass.prototype
而不是直接分配给 superClass.prototype
,而是通过合并该对象和另一组默认属性创建的对象。
有了这个原型链,继承将起作用,但 instanceof 运算符将无法通过引用遍历它,所以你得到 false
你期望的 true
.
显然,根据 this bug report, it's a known and expected behaviour (ie. limitation) and a possible workaround is to use babel-plugin-transform-builtin-extend
TypeScript 有这个问题。通过在 super 调用后的 class 构造函数中添加以下内容解决了这个问题:
Object.setPrototypeOf(this, YOUR_CLASS_HERE.prototype);
不确定是否对您有帮助。
在我的例子中,instanceof
无法使用设置为“es5”的编译目标。当更改为“es6”时,它产生了正确的结果。
使用 ES6 class
语法,我想知道当有多个继承链时,为什么 instanceof
运算符对继承链不起作用?
(optional read)How
instanceof
operator works?In
obj instanceof Constructor
, theinstanceof
operator checks if the'prototype'
property of theConstructor
function is present in the prototype chain of theobj
. If it is present, returntrue
. Otherwise,false
.
在下面的代码片段中,BTError
继承自 Error
(1.) 和 SomeError
扩展自 BTError
(3.).
但是正如我们从 (4. 中看到的那样,instanceof
运算符结果 false
for new SomeError() instanceof BTError
在我的理解中应该是 true
.
class BTError extends Error {}
console.log('1.', Reflect.getPrototypeOf(BTError.prototype) === Error.prototype); // 1. true
console.log('2.', new BTError() instanceof Error); // 2. true
console.log('');
class SomeError extends BTError {}
console.log('3.', Reflect.getPrototypeOf(SomeError.prototype) === BTError.prototype); // 3. true
console.log('4.', new SomeError() instanceof BTError); // 4. false
console.log('');
class SpecificError extends SomeError {}
console.log('5.', Reflect.getPrototypeOf(SpecificError.prototype) === SomeError.prototype); // 5. true
console.log('6.', new SpecificError() instanceof Error); // 6. true
console.log('7.', new SpecificError() instanceof BTError); // 7. false
console.log('8.', new SpecificError() instanceof SomeError); // 8. false
问题
是否有任何我无法理解的重要事情,或者 instanceof
操作员只是在表现 怪异 ?
关注示例的最后一部分
您正在使用 BabelJS 转换此代码以使其兼容
class BTError extends Error {}
class SomeError extends BTError {}
class SpecificError extends SomeError {}
console.log('6.', new SpecificError() instanceof Error);
console.log('7.', new SpecificError() instanceof BTError);
console.log('8.', new SpecificError() instanceof SomeError);
这是上面代码的转译版本
'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 BTError = function(_Error) {
_inherits(BTError, _Error);
function BTError() {
_classCallCheck(this, BTError);
return _possibleConstructorReturn(this, (BTError.__proto__ || Object.getPrototypeOf(BTError)).apply(this, arguments));
}
return BTError;
}(Error);
var SomeError = function(_BTError) {
_inherits(SomeError, _BTError);
function SomeError() {
_classCallCheck(this, SomeError);
return _possibleConstructorReturn(this, (SomeError.__proto__ || Object.getPrototypeOf(SomeError)).apply(this, arguments));
}
return SomeError;
}(BTError);
var SpecificError = function(_SomeError) {
_inherits(SpecificError, _SomeError);
function SpecificError() {
_classCallCheck(this, SpecificError);
return _possibleConstructorReturn(this, (SpecificError.__proto__ || Object.getPrototypeOf(SpecificError)).apply(this, arguments));
}
return SpecificError;
}(SomeError);
console.log('6.', new SpecificError() instanceof Error); // 6. true
console.log('7.', new SpecificError() instanceof BTError); // 7. false
console.log('8.', new SpecificError() instanceof SomeError); // 8. false
我认为问题出在 _inherit
方法,该方法分配给 subClass.prototype
而不是直接分配给 superClass.prototype
,而是通过合并该对象和另一组默认属性创建的对象。
有了这个原型链,继承将起作用,但 instanceof 运算符将无法通过引用遍历它,所以你得到 false
你期望的 true
.
显然,根据 this bug report, it's a known and expected behaviour (ie. limitation) and a possible workaround is to use babel-plugin-transform-builtin-extend
TypeScript 有这个问题。通过在 super 调用后的 class 构造函数中添加以下内容解决了这个问题:
Object.setPrototypeOf(this, YOUR_CLASS_HERE.prototype);
不确定是否对您有帮助。
在我的例子中,instanceof
无法使用设置为“es5”的编译目标。当更改为“es6”时,它产生了正确的结果。