Map.prototype.has()
map.has(key) The has() method returns a boolean indicating whether a Map contains a specific key. Key comparison uses the SameValueZero algorithm — the same rule the Map uses when storing entries. This means object keys are compared by reference, not by value, and NaN is treated as equal to itself.
Unlike checking property existence on a plain object with in or hasOwnProperty, has() only looks at the Map’s own entries and never traverses a prototype chain.
Syntax
map.has(key)
Parameters
| Parameter | Type | Description |
|---|---|---|
key | any | The key to check for in the Map |
Return value
true if the key exists in the Map, false otherwise. Unlike get(), which returns undefined for both missing keys and keys set to undefined, the return value of has() unambiguously tells you whether the key was stored.
Examples
Basic usage
const userRoles = new Map();
userRoles.set('alice', 'admin');
userRoles.set('bob', 'editor');
console.log(userRoles.has('alice'));
// true
console.log(userRoles.has('unknown'));
// false
With string keys, has() behaves like a straightforward membership check. Object keys introduce an important twist: the SameValueZero algorithm compares by identity, not by structural equality. Two objects with the same shape are not the same key — only the exact object reference you originally used will match.
Using with object keys
const visits = new Map();
const page1 = { path: '/home', lang: 'en' };
visits.set(page1, 1500);
console.log(visits.has(page1));
// true
// Different object reference - not found
console.log(visits.has({ path: '/home', lang: 'en' }));
// false
Two objects with identical structure are not the same key. The Map stores the original object reference and compares by identity. This matters when you use has() to check for object-keyed entries: you must hold a reference to the original object that was used as the key, because a freshly-created object with the same properties will not match.
Conditional value retrieval
const cache = new Map();
function getCached(key) {
if (!cache.has(key)) {
return null;
}
return cache.get(key);
}
cache.set('users', ['alice', 'bob']);
console.log(getCached('users')); // ['alice', 'bob']
console.log(getCached('missing')); // null
Checking with has() before calling get() is the safest pattern when undefined is a valid stored value, because get() returns undefined for both missing keys and keys explicitly set to undefined. The same pattern applies when you need to confirm a key’s presence before performing a side effect, such as logging or deleting the entry.
Before delete operation
const queue = new Map([['job1', { status: 'running' }]]);
function cancelJob(jobId) {
if (!queue.has(jobId)) {
console.log(`Job ${jobId} not found`);
return false;
}
queue.delete(jobId);
console.log(`Job ${jobId} cancelled`);
return true;
}
cancelJob('job1'); // Job job1 cancelled
cancelJob('job2'); // Job job2 not found
The previous examples show has() used for lookups. It is equally useful as a guard for mutation — checking before writing or deleting avoids accidental overwrites and keeps error messages precise. The following two patterns demonstrate these guards in practice.
Common patterns
Prevent overwriting existing entries
const registry = new Map();
function register(name, handler) {
if (registry.has(name)) {
throw new Error(`Handler ${name} already registered`);
}
registry.set(name, handler);
}
register('init', () => {});
register('init', () => {}); // Throws Error
The prevent-overwrite pattern above is useful for registries where duplicate keys are errors. When duplicates are allowed but you still need to know whether a lookup will succeed, has() works well as a log-before-access guard — confirming existence without modifying the map.
Key existence before access
const configs = new Map([
['production', { debug: false }],
['development', { debug: true }]
]);
function getConfig(env) {
const exists = configs.has(env);
console.log(`Config for ${env} exists: ${exists}`);
return configs.get(env);
}
getConfig('production'); // Config for production exists: true
getConfig('staging'); // Config for staging exists: false
Comparing with plain objects
When working with a plain object you might check property existence with the in operator or Object.prototype.hasOwnProperty. Both have edge cases: in traverses the prototype chain and can match inherited properties, and hasOwnProperty can be shadowed by a property with the same name. Map.prototype.has() has neither issue — it only checks entries you explicitly added, and the method cannot be shadowed because you call it through the Map prototype, not as a property on the map itself.
const obj = {};
console.log('toString' in obj); // true — inherited from Object.prototype
const map = new Map();
console.log(map.has('toString')); // false — only checks map entries
Performance
has() runs in O(1) average time, the same as get() and set(). The underlying hash table means the lookup time does not increase as the Map grows. For large collections where you need to repeatedly check membership, a Map (or Set) is far more efficient than searching an array with includes() or find().
When has() is the right check
Map.prototype.has() is the right choice when the question is simply whether a key exists. That makes it a natural companion to get(), especially when undefined can be a real stored value. By checking existence first, you can tell the difference between “missing” and “present but empty” without relying on the return value of get().
It is also a good fit for cache lookups and registry-style data where keys are meant to be unique. In those cases, has() keeps the intent clear: you are asking about membership, not about the value itself. That distinction makes the code easier to follow and helps avoid accidental overwrites or mistaken fallback logic.