检查对象是否是 class 的 'direct instance'

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

我有两个类:

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

Bar constructor 检查 value 是否是 Foo 的实例,如果不是则抛出错误。至少,那是我想要它做的。如果您传递 BarBaz 作为值,if 语句 returns true 也是如此。目标是只让Foo通过。
我已经找到了 this answer,但这并没有真正回答我的问题。

如果您知道所有 类 您可以使用

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

检查构造函数:

if (!value || value.constructor !== Foo)
  throw 'InvalidArgumentException: (...)';

或对象的原型(这更类似于instanceof所做的):

if (!value || Object.getPrototypeOf(value) !== Foo.prototype)
  throw 'InvalidArgumentException: (...)';

问题是您引用的所有 类 都是 Foo 的后代。这样 new Baz() instanceOf Bar && new Bar() instanceOf Foo === true。 所以当你问是Bar instanceOf Foo时,通过继承它会是真的。

由于 JS 中没有 Java getClass() 等价物,您应该使用类似的东西:

if (value.constructor.name !== Foo.name)

您可以使用 Object.getPrototypeOf(yourObj)Foo.prototype 之间的比较来查看 yourObj 是否恰好是 Foo 的实例。您可以通过继续为每个级别调用 Object.getPrototypeOf 来向上移动链。

示例:

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

您应该测试 value 的内部 [[Prototype]] 是否恰好是 Foo.prototype。您可以使用 Object.getPrototypeOf 获得内部 [[Prototype]] :

if ( Object.getPrototypeOf( value ) !== Foo.prototype )
   throw "InvalidArgumentException: (...)";

我创造了检查 DOM 类 和元素

之间关系的函数
const getCreator = instance => Object.getPrototypeOf(instance).constructor.name;
// usage
getCreator(document.documentElement) === "HTMLHtmlElement;