I just want to check that an object is a Map
or Set
and not an Array
.
to check an Array I'm using lodash's _.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 does it need to look like? I'd like for it to be able to catch subclasses of Map
/Set
if possible as well.
Use the instanceof operator to check if an object is a Map - myObj instanceof Map . The instanceof operator returns true if the prototype property of a constructor appears in the prototype chain of the object.
The Map.has() method in JavaScript is used to check whether an element with a specified key exists in a map or not. It returns a boolean value indicating the presence or absence of an element with a specified key in a map.
ECMAScript 6 formally introduces sets and maps into JavaScript. Prior to this, developers frequently used objects to mimic both sets and maps, often running into problems due to the limitations associated with object properties. Sets are unordered lists of unique values.
The ECMAScript 6 WeakMap type is an unordered list of key-value pairs, where a key must be a non-null object and a value can be of any type. The interface for WeakMap is very similar to that of Map in that set () and get () are used to add and retrieve data, respectively:
The Map data structure in ECMAScript 6 lets you use arbitrary values as keys and is highly welcome. Working with single entries: Determining the size of a map and clearing it: You can set up a map via an iterable over key-value “pairs” (arrays with 2 elements). One possibility is to use an array (which is iterable): What keys are considered equal?
ECMAScript 5 doesn’t have a set data structure, either. There are two possible work-arounds: Use the keys of an object to store the elements of a set of strings. Store (arbitrary) set elements in an array: Check whether it contains an element via indexOf (), remove elements via filter (), etc.
The situation is similar to pre-ES5 methods to detect arrays properly and reliably. See this great article for the possible pitfalls of implementing isArray
.
We can use
obj.constructor == Map
/Set
, but that doesn't work on subclass instances (and can easily be deceived)obj instanceof Map
/Set
, but that still doesn't work across realms (and can be deceived by prototype mangling)obj[Symbol.toStringTag] == "Map"
/"Set"
, but that can trivially be deceived again.To be really sure, we'd need to test whether an object has a [[MapData]]
/[[SetData]]
internal slot. Which is not so easily accessible - it's internal. We can use a hack, though:
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 common use, I'd recommend instanceof
- it's simple, understandable, performant, and works for most reasonable cases. Or you go for duck typing right away and only check whether the object has has
/get
/set
/delete
/add
/delete
methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With