检查对象是不是是类的“直接实例”
Posted
技术标签:
【中文标题】检查对象是不是是类的“直接实例”【英文标题】:Check if object is a 'direct instance' of a class检查对象是否是类的“直接实例” 【发布时间】:2018-08-31 05:00:13 【问题描述】:我有两个班级:
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 的实例,如果不是则抛出错误。至少,这就是我想要它做的。如果您传递 Bar
或 Baz
作为值,则 if 语句也会返回 true
。目标是只让Foo
s 通过。
我已经找到了this answer,但这并没有真正回答我的问题。
【问题讨论】:
This answer 来自您链接的其他问题似乎有效。只有使用new Foo()
创建的 Foo 对象在调用 foo.constructor.name
时会返回“Foo”
你认为你需要这个做什么?您似乎在滥用继承,因为您的目标是破坏Liskov Substitution Principle。不要那样做。每个Bar
和Baz
实例都应该在您希望拥有Foo
实例的地方有效。
【参考方案1】:
如果你知道所有你可以使用的类
if(!(value instanceof Foo && !(value instanceof Bar) && !(value instanceof Baz)))
【讨论】:
@Sacha 请查看我的答案以对其他类进行通用检查【参考方案2】:检查构造函数:
if (!value || value.constructor !== Foo)
throw 'InvalidArgumentException: (...)';
或对象的原型(这更类似于instanceof
所做的):
if (!value || Object.getPrototypeOf(value) !== Foo.prototype)
throw 'InvalidArgumentException: (...)';
【讨论】:
这没有回答核心问题。它没有解决继承问题。【参考方案3】:问题是您引用的所有类都是Foo
的后代。这样new Baz() instanceOf Bar && new Bar() instanceOf Foo === true
。
所以当你问的是 Bar instanceOf Foo 时,通过继承就会为真。
由于 JS 中没有 Java getClass()
等价物,您应该使用类似:
if (value.constructor.name !== Foo.name)
【讨论】:
Java 中的getClass()
做了什么而 value.constructor
在 JS 中没有?
你永远不应该比较类的名称。它们可能被缩小器破坏,它们可能被优化掉,它们可能被覆盖或伪造。永远不要依赖名字。【参考方案4】:
您可以使用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);
【讨论】:
【参考方案5】:您应该测试value
的内部[[Prototype]]
是否正好是Foo.prototype
。您可以通过Object.getPrototypeOf 获取内部[[Prototype]]
:
if ( Object.getPrototypeOf( value ) !== Foo.prototype )
throw "InvalidArgumentException: (...)";
【讨论】:
【参考方案6】:我创造了检查 DOM 类和元素之间关系的函数
const getCreator = instance => Object.getPrototypeOf(instance).constructor.name;
// usage
getCreator(document.documentElement) === "htmlHtmlElement;
【讨论】:
以上是关于检查对象是不是是类的“直接实例”的主要内容,如果未能解决你的问题,请参考以下文章