abh*_*ekp 10 javascript inheritance class ecmascript-6 es6-class
使用ES6 class语法,我想知道为什么instanceof当有多个继承链时,运算符不适用于继承链?
(可选阅读)
instanceof操作员如何工作?在
obj instanceof Constructor,instanceof操作员检查函数的'prototype'属性Constructor是否存在于原型链中obj.如果它存在,请返回true.否则,false.
在下面的代码片段中,BTError继承自Error(1.)并SomeError从BTError(3.)扩展.
但是,正如我们可以看到从(4),该instanceof操作结果false为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. falseRun Code Online (Sandbox Code Playgroud)
有什么重要的事情我无法理解或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);Run Code Online (Sandbox Code Playgroud)
这是上面代码的转换版本
'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. falseRun Code Online (Sandbox Code Playgroud)
我认为问题源于_inherit方法,它subClass.prototype不是superClass.prototype直接分配,而是通过合并该方法和另一组默认属性创建的对象.
通过这个原型链,继承可以工作,但是instanceof运算符将无法通过引用传递它,因此您可以获得false预期的位置true.
显然,根据这个错误报告,这是一个已知的和预期的行为(即限制),可能的解决方法是使用babel-plugin-transform-builtin-extend
TypeScript 有这个问题。通过在超级调用后的类构造函数中添加以下内容来解决它:
Object.setPrototypeOf(this, YOUR_CLASS_HERE.prototype);
Run Code Online (Sandbox Code Playgroud)
不确定它是否对你有帮助。