How to reliably verify an object is EcmaScript 6 Map / Set?

I just want to verify that the object is a Map or Set , not an Array .

to check the array I use lodash _.isArray .

 function myFunc(arg) { if (_.isArray(arg)) { // doSomethingWithArray(arg) } if (isMap(arg)) { // doSomethingWithMap(arg) } if (isSet(arg)) { // doSomethingWithSet(arg) } } 

If I were to implement isMap / isSet , what should it look like? I would like it to catch subclasses of Map / Set , if possible.

+6
source share
2 answers

The situation is similar to pre-ES5 methods for the correct and reliable detection of arrays. See this great article for possible pitfalls of isArray implementation.

We can use

  • obj.constructor == Map / Set , but this does not work on instances of the subclass (and can be easily fooled)
  • obj instanceof Map / Set , but this still doesn't work across spheres (and can be tricked with the prototype mangling)
  • obj[Symbol.toStringTag] == "Map" / "Set" , but this can be trivially tricked again.

To be sure, we need to check if the object has an internal [[MapData]] / [[SetData]] . Which is not so easily accessible - it is internal. However, we can use the hack:

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

For general use, I would recommend instanceof - it is simple, understandable, efficient and works in the most reasonable cases. Or, you immediately type a duck and check to see if the object has / get / Set / delete / add / delete methods.

+12
source

You can use instanceof operator:

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

If the candidate object has Set.prototype in its prototype chain, the instanceof operator returns true .

edit - while the instanceof thing will work most of the time, there are situations in which it will not, as described in Bergi's answer.

+4
source

Source: https://habr.com/ru/post/986167/


All Articles