我只是想检查的对象是一个Map
或Set
,而不是一个Array
。
检查我使用lodash的数组_.isArray
。
function myFunc(arg) {
if (_.isArray(arg)) {
// doSomethingWithArray(arg)
}
if (isMap(arg)) {
// doSomethingWithMap(arg)
}
if (isSet(arg)) {
// doSomethingWithSet(arg)
}
}
如果我要实现isMap
/ isSet
,这是什么需要什么样子的? 我想为它能够赶上的子类Map
/ Set
,如果可能的。
这种情况类似于预ES5方法正确和可靠地检测阵列。 请参阅这篇大文章实现的可能的陷阱isArray
。
我们可以用
-
obj.constructor == Map
/ Set
,但这并不在子类的实例工作(并可以很容易地被欺骗) -
obj instanceof Map
/ Set
,但仍然无法跨领域工作(并可以通过原型忙玲被欺骗) -
obj[Symbol.toStringTag] == "Map"
/ "Set"
,但可以平凡再次上当受骗。
为了真正肯定的是,我们需要测试一个对象是否具有[[MapData]]
/ [[SetData]]
内部插槽。 这不是那么容易接近 - 这是内部的。 我们可以用一个黑客,但:
function isMap(o) {
try {
Map.prototype.has.call(o); // throws if o is not an object or has no [[MapData]]
return true;
} catch(e) {
return false;
}
}
function isSet(o) {
try {
Set.prototype.has.call(o); // throws if o is not an object or has no [[SetData]]
return true;
} catch(e) {
return false;
}
}
对于一般的使用,我建议你instanceof
-这是简单,易懂,高性能,并适用于最合理的情况下。 或者你去鸭打字的时候了,只有检查对象是否已经has
/ get
/ set
/ delete
/ add
/ delete
方法。
您可以使用instanceof
运算符:
function isSet(candidate) {
return candidate instanceof Set;
}
如果候选对象Set.prototype
在其原型链,那么instanceof
运算符返回true
。
编辑 -而instanceof
事会工作的大部分时间,在有些情况下,它不会像在BERGI的答案描述。