问题
I have two classes:
class Bar extends Foo { // Foo isn't relevant
constructor(value) {
if (!(value instanceof Foo)) throw "InvalidArgumentException: (...)";
super();
this.value = value;
}
}
class Baz extends Bar {
constructor(value) {
super(value);
}
}
The Bar
constructor
checks if value
is an instance of Foo, it throws an error if it isn't. At least, that's what I wanted it to do. If you pass a Bar
or a Baz
as value, the if-statement returns true
as well. The goal is to only let Foo
s through.
I found this answer already but that didn't really answer my question.
回答1:
Check the constructor:
if (!value || value.constructor !== Foo)
throw 'InvalidArgumentException: (...)';
or the prototype of the object (this is more similar to what instanceof
does):
if (!value || Object.getPrototypeOf(value) !== Foo.prototype)
throw 'InvalidArgumentException: (...)';
回答2:
You can use a comparison between Object.getPrototypeOf(yourObj)
and Foo.prototype
to see if yourObj
is exactly an instance of Foo
. And you can move up the chain by just continuing to call Object.getPrototypeOf
for each level.
Example:
class Foo {}
class Bar extends Foo {}
class Baz extends Bar {}
const foo = new Foo();
const bar = new Bar();
const baz = new Baz();
// For this function:
// - level 0 is self
// - level 1 is parent
// - level 2 is grandparent
// and so on.
function getPrototypeAt(level, obj) {
let proto = Object.getPrototypeOf(obj);
while (level--) proto = Object.getPrototypeOf(proto);
return proto;
}
console.log("bar is a foo:", bar instanceof Foo);
console.log("baz is a foo:", baz instanceof Foo);
console.log("foo is exactly a foo:", getPrototypeAt(0, foo) === Foo.prototype);
console.log("bar is exactly a foo:", getPrototypeAt(0, bar) === Foo.prototype);
console.log("bar is direct child of foo:", getPrototypeAt(1, bar) === Foo.prototype);
console.log("baz is direct child of foo:", getPrototypeAt(1, baz) === Foo.prototype);
console.log("baz is direct child of bar:", getPrototypeAt(1, baz) === Bar.prototype);
console.log("baz is grandchild of foo:", getPrototypeAt(2, baz) === Foo.prototype);
回答3:
You should test if value
's internal [[Prototype]]
is exactly Foo.prototype
. You can get the internal [[Prototype]]
with Object.getPrototypeOf :
if ( Object.getPrototypeOf( value ) !== Foo.prototype )
throw "InvalidArgumentException: (...)";
回答4:
If you know all of your classes you can use
if(!(value instanceof Foo && !(value instanceof Bar) && !(value instanceof Baz)))
回答5:
I coined the function for checking relationships between DOM Classes and elements
const getCreator = instance => Object.getPrototypeOf(instance).constructor.name;
// usage
getCreator(document.documentElement) === "HTMLHtmlElement;
回答6:
The problem is that all of your classes you reference are descendants of Foo
. Such that new Baz() instanceOf Bar && new Bar() instanceOf Foo === true
.
So when you ask is Bar instanceOf Foo, it will be true through inheritance.
Due to there being no Java getClass()
equivalent in JS, you should use something like:
if (value.constructor.name !== Foo.name)
来源:https://stackoverflow.com/questions/49417099/check-if-object-is-a-direct-instance-of-a-class