gotchajavascriptModeratepending
Gotcha: JavaScript Set and Map compare objects by reference
Viewed 0 times
SetMapreferenceequalitydedupunique
Error Messages
Problem
Adding two identical objects to a Set results in two entries because Set uses reference equality, not value equality.
Solution
Set and Map compare non-primitive values by reference:
// Objects:
const set = new Set();
set.add({ x: 1 });
set.add({ x: 1 }); // Different reference!
console.log(set.size); // 2, not 1!
// Same with Map keys:
const map = new Map();
map.set({ id: 1 }, 'a');
map.set({ id: 1 }, 'b'); // Different key!
console.log(map.size); // 2
// Workarounds:
// 1. Use primitive keys:
const byId = new Map();
byId.set(1, user1); // Numbers are compared by value
// 2. Use JSON strings as keys:
const seen = new Set();
for (const obj of items) {
const key = JSON.stringify(obj);
if (seen.has(key)) continue;
seen.add(key);
// process unique obj
}
// 3. Use a custom key function:
function uniqueBy(arr, keyFn) {
const seen = new Set();
return arr.filter(item => {
const key = keyFn(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
const unique = uniqueBy(users, u => u.id);
// Objects:
const set = new Set();
set.add({ x: 1 });
set.add({ x: 1 }); // Different reference!
console.log(set.size); // 2, not 1!
// Same with Map keys:
const map = new Map();
map.set({ id: 1 }, 'a');
map.set({ id: 1 }, 'b'); // Different key!
console.log(map.size); // 2
// Workarounds:
// 1. Use primitive keys:
const byId = new Map();
byId.set(1, user1); // Numbers are compared by value
// 2. Use JSON strings as keys:
const seen = new Set();
for (const obj of items) {
const key = JSON.stringify(obj);
if (seen.has(key)) continue;
seen.add(key);
// process unique obj
}
// 3. Use a custom key function:
function uniqueBy(arr, keyFn) {
const seen = new Set();
return arr.filter(item => {
const key = keyFn(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
const unique = uniqueBy(users, u => u.id);
Why
JavaScript has no structural equality for objects. {} === {} is false because they are different object instances in memory.
Revisions (0)
No revisions yet.