如何可靠地检查的对象是EcmaScript的6地图/设置?如何可靠地检查的对象是EcmaScript

2019-05-12 10:14发布

我只是想检查的对象是一个MapSet ,而不是一个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 ,如果可能的。

Answer 1:

这种情况类似于预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方法。



Answer 2:

您可以使用instanceof运算符:

function isSet(candidate) {
  return candidate instanceof Set;
}

如果候选对象Set.prototype在其原型链,那么instanceof运算符返回true

编辑 -而instanceof事会工作的大部分时间,在有些情况下,它不会像在BERGI的答案描述。



文章来源: How to reliably check an object is an EcmaScript 6 Map/Set?