ES6 class
構文を使用して、継承のチェーンが複数あるのに、なぜinstanceof
演算子が継承チェーンに対して機能しないのか疑問に思いますか?
(オプションの読み取り)
instanceof
演算子はどのように機能しますか?_
obj instanceof Constructor
_では、instanceof
演算子は、Constructor
関数の_'prototype'
_プロパティがプロトタイプobj
のチェーン。存在する場合は、true
を返します。それ以外の場合は、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
を取得します。
どうやら、 このバグレポート によると、これは既知の予想される動作(つまり制限)であり、考えられる回避策は babel-plugin-transform-builtin-extend を使用することです。