简体   繁体   中英

Check if object is a 'direct instance' of a class

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.

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: (...)';

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); 

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: (...)";

如果你知道你可以使用的所有课程

if(!(value instanceof Foo && !(value instanceof Bar) && !(value instanceof Baz)))

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)

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM