问题
I have a situation where I need to check if a constructor (X) has another constructor (Y) in its prototype chain (or is Y itself).
The quickest means to do this might be (new X()) instanceof Y
. That isn't an option in this case because the constructors in question may throw if instantiated without valid arguments.
The next approach I've considered is this:
const doesInherit = (A, B) => {
while (A) {
if (A === B) return true;
A = Object.getPrototypeOf(A);
}
return false;
}
That works, but I can't shake the sense that I'm missing some more straightforward way to check this. Is there one?
回答1:
Because of the way instanceof
works, you should be able to do
A.prototype instanceof B
But this would only test inheritance, you should have to compare A === B
to test for self-reference:
A === B || A.prototype instanceof B
Babel example:
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
is basically implemented as follows:
function instanceof(obj, Constr) {
var proto;
while ((proto = Object.getProtoypeOf(obj)) {
if (proto === Constr.prototype) {
return true;
}
}
return false;
}
It iterates over the prototype chain of the object and checks whether any of the prototypes equals the constructors prototype
property.
So almost like what you were doing, but internally.
回答2:
There's also Object.prototype.isPrototypeOf(). Seems like a perfect use case, no?
Babel
class A {}
class B extends A {}
class C extends B {}
console.log(C === C)
console.log(B.isPrototypeOf(C))
console.log(A.isPrototypeOf(C))
回答3:
BEWARE: The above answer of checking ES6 classes A, B, C inheritance-chain with isPrototypeOf() works great. But it doesn't work like you might expect for pre-ES6 classes Object, Array, Function etc.
Object.prototype.isPrototypeOf (Array.prototype); // => true
But:
Object.isPrototypeOf (Array); // => false
This is like it should be. INSTANCES of Array inherit the methods of Object.prototype. But the "class" Array does NOT inherit the "class" Object. If you add a method to Object you can not call it via Array. Array does not inherit methods of Object (if any). It's just that user-created classes work differently!
Perhaps we should not think of Object and Array and Function as "classes" at all - even though you can create instances of them. They are only "constructors". Or we can say that they are classes but that built-in classes in JavaScript work differently from user-created ones.
来源:https://stackoverflow.com/questions/30993434/check-if-a-constructor-inherits-another-in-es6