コンストラクター(X)のプロトタイプチェーンに別のコンストラクター(Y)があるかどうか(またはY自体であるかどうか)を確認する必要がある状況があります。
これを行う最も簡単な方法は(new X()) instanceof Y
。この場合、有効な引数なしでインスタンス化された場合、問題のコンストラクターがスローする可能性があるため、これはオプションではありません。
私が検討した次のアプローチはこれです:
const doesInherit = (A, B) => {
while (A) {
if (A === B) return true;
A = Object.getPrototypeOf(A);
}
return false;
}
それはうまくいきますが、これをチェックするためのもっと簡単な方法が欠けているという感覚を揺るがすことはできません。ありますか?
instanceof
の動作方法により、次のことができるはずです。
A.prototype instanceof B
ただし、これは継承をテストするだけなので、自己参照をテストするにはA === B
を比較する必要があります。
A === B || A.prototype instanceof B
Babelの例 :
class A {}
class B extends A {}
class C extends B {}
console.log(C === C) // true
console.log(C.prototype instanceof B) // true
console.log(C.prototype instanceof A) // true
instanceof
は基本的に次のように実装されます。
function instanceof(obj, Constr) {
var proto;
while ((proto = Object.getProtoypeOf(obj)) {
if (proto === Constr.prototype) {
return true;
}
}
return false;
}
オブジェクトのプロトタイプチェーンを反復処理し、プロトタイプのいずれかがコンストラクターprototype
プロパティと等しいかどうかを確認します。
ですから、あなたがやっていたこととほとんど同じですが、内部的には。
Object.prototype.isPrototypeOf()
もあります。完璧なユースケースのようですよね?
class A {}
class B extends A {}
class C extends B {}
console.log(C === C)
console.log(B.isPrototypeOf(C))
console.log(A.isPrototypeOf(C))
注意:isPrototypeOf()を使用してES6クラスA、B、Cの継承チェーンをチェックする上記の回答はうまく機能します。ただし、ES6より前のクラスであるObject、Array、Functionなどでは期待どおりには機能しません。
Object.prototype.isPrototypeOf (Array.prototype); // => true
だが:
Object.isPrototypeOf (Array); // => false
これはあるべき姿です。配列のインスタンスは、Object.prototypeのメソッドを継承します。ただし、「クラス」配列は「クラス」オブジェクトを継承しません。 Objectにメソッドを追加した場合、Arrayを介してメソッドを呼び出すことはできません。配列はオブジェクトのメソッドを継承しません(存在する場合)。ユーザーが作成したクラスの動作が異なるだけです。
おそらく、オブジェクト、配列、関数を「クラス」と見なすべきではありません。インスタンスを作成できたとしてもです。彼らはただの「コンストラクター」です。または、それらはクラスであると言えますが、JavaScriptの組み込みクラスは、ユーザーが作成したクラスとは動作が異なります。