Reputation: 1708
Is there any advantage to use Map.has()
for checking if key exists in Map
instead of using Map.get()
? (Other than code readability reasons)
I checked ES2015 language specifications and both methods seems the same except the return value so I believe the performance is the same but maybe there are some other aspects I don't know of that could affect performance here.
Map.prototype.has ( key )
The following steps are taken:
Let M be the this value. If Type(M) is not Object, throw a TypeError exception. If M does not have a [[MapData]] internal slot, throw a TypeError exception. Let entries be the List that is the value of M’s [[MapData]] internal slot. Repeat for each Record {[[key]], [[value]]} p that is an element of entries, If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, return true. Return false.
Map.prototype.has method specification
Map.prototype.get ( key )
The following steps are taken:
Let M be the this value. If Type(M) is not Object, throw a TypeError exception. If M does not have a [[MapData]] internal slot, throw a TypeError exception. Let entries be the List that is the value of M’s [[MapData]] internal slot. Repeat for each Record {[[key]], [[value]]} p that is an element of entries, If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, return p.[[value]]. Return undefined.
Map.prototype.get method specification
Upvotes: 21
Views: 7047
Reputation: 23
Let's say we're storing Objects into a Map :
const myMap = new Map(/* collection of objects */);`
In code samples, we can ofen see this :
function search(key) {
if (myMap.has(key)) return null;
let obj = myMap.get(key);
return obj;
}
In case the key exists in the Map, we're searching for it 2 times : .has() then .get() !
The function can be optimized this way :
function search(key) {
const obj = myMap.get(key);
return obj || null;
}
But what if, instead of Objects we're storing primitive values ?
If the key exists, but its associated value is falsy (zero, false, empty string...), the last line will return null !
Of course, we could do this : return obj !== undefined ? obj : null
But we're lazy programmers, so let's use the nullish coalescing operator ??
function search(key) {
const value = myMap.get(key);
return value ?? null;
}
This will do the trick, wether we're dealing with Objects or primitive values :-)
Personnally, I never use the Map.prototype.has() method. Do you know examples where it could be useful ?
Upvotes: 0
Reputation: 371019
One reason why Map.has
could be preferable would be if the key happens to exist, but the value is falsey. If you use Map.get
, you'll also have to check whether the value === undefined
(and even that does not guarantee that the key does not exist - the key may exist, but have a value of undefined
):
// Not good enough:
const map = new Map();
map.set('foo', 0);
if (map.get('foo')) {
console.log('Map has "foo" key');
}
// Better, but not foolproof:
const map = new Map();
map.set('foo', 0);
map.set('bar', undefined);
const valAtFoo = map.get('foo');
if (valAtFoo !== undefined) {
console.log('Map has "foo" key');
}
// Incorrect:
const valAtBar = map.get('bar');
if (valAtBar !== undefined) {
console.log('Map has "bar" key');
}
// Solution: use map.has instead of map.get
const map = new Map();
map.set('foo', 0);
map.set('bar', undefined);
if (map.has('foo')) {
console.log('Map has "foo" key');
}
if (map.has('bar')) {
console.log('Map has "bar" key');
}
You would use Map.has
for the same reason that you would use Object.prototype.hasOwnProperty
for checking whether an object has a certain property - using obj[prop]
to check if the prop
exists just isn't good enough in certain cases.
It's not an issue of performance - rather, it's because in some cases, there's just no other way. (.has
is also more readable, though you said to ignore that part)
Upvotes: 27