Unveiling JavaScript Map: Mastering Key-Value Storage
Unlock the full potential of JavaScript's Map and WeakMap—from efficient key-value storage to advanced memory management techniques.
1. From Bronze to King: Why Do We Need Map?
In JavaScript, objects were originally used to store key-value pairs. However, they come with a major drawback—non-string keys are automatically converted to strings.
const obj = {};
const key = { id: 1 };
obj[key] = 'value';
console.log(obj['[object Object]']); // 'value'To address this, ES6 introduced Map, a robust data structure that supports any type of key.
const map = new Map();
const ironKey = { id: 1 };
map.set(ironKey, 'Vibranium Shield');
console.log(map.get(ironKey)); // 'Vibranium Shield'2. Six Unique Features of Map
Any Type of Key: Supports objects, functions, NaN, and more.
Preserves Insertion Order: Iterating over a
Mapmaintains order.Built-in Size Property: Access
map.sizedirectly.Optimized for Frequent Operations: Performs better than objects for large data sets.
Supports Direct Iteration: Use
for...ofwithout conversion.Pure Key-Value Storage: Does not inherit from
Object.prototype, preventing prototype chain conflicts.
3. Mastering Map Operations
3.1 Basic Operations
const jediCouncil = new Map([
['Yoda', 'Master'],
['Mace Windu', 'Council Head']
]);
jediCouncil.set('Anakin', 'Chosen One');
jediCouncil.delete('Anakin');
console.log(jediCouncil.has('Yoda')); // true
console.log(jediCouncil.size); // 23.2 Iteration Methods
for (const [jedi, title] of jediCouncil) {
console.log(`${jedi}: ${title}`);
}
const keys = jediCouncil.keys();
console.log(keys.next().value); // 'Yoda'3.3 Implementing an LRU Cache
class LRUCache {
constructor(capacity) {
this.cache = new Map();
this.capacity = capacity;
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) this.cache.delete(key);
if (this.cache.size >= this.capacity) {
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}
this.cache.set(key, value);
}
}4. WeakMap: The Memory Management Warrior
WeakMap holds weak references to objects, allowing garbage collection when there are no other references.
let deathStar = { target: 'Alderaan' };
const weakMap = new WeakMap();
weakMap.set(deathStar, 'Operational');
deathStar = null;4.1 WeakMap Key Rules
Keys must be objects.
Cannot be iterated.
No
sizeproperty.
4.2 Real-World Usage
Private Data Storage
const privateData = new WeakMap();
class Jedi {
constructor(name) {
privateData.set(this, { name });
}
get name() {
return privateData.get(this).name;
}
}Managing DOM Metadata
const domMetadata = new WeakMap();
const button = document.querySelector('#btn');
domMetadata.set(button, { clickCount: 0 });
button.addEventListener('click', () => {
const data = domMetadata.get(button);
data.clickCount++;
});5. Advanced Example: Caching API Responses
Using Map to cache API responses for better performance.
class APICache {
constructor(ttl = 5000) {
this.cache = new Map();
this.ttl = ttl;
}
async fetchData(url) {
if (this.cache.has(url)) {
const { timestamp, data } = this.cache.get(url);
if (Date.now() - timestamp < this.ttl) {
return data;
}
}
const response = await fetch(url);
const data = await response.json();
this.cache.set(url, { timestamp: Date.now(), data });
return data;
}
}6. Choosing Between Map and WeakMap
Need iteration? → Use
MapHandling short-lived data? → Use
WeakMapKeys are objects tied to lifecycle? → Use
WeakMapNeed a size property? → Use
MapAvoid memory leaks? → Use
WeakMap
JavaScript’s Map and WeakMap play crucial roles in structured data storage and memory-efficient applications. Choosing the right tool makes your code more elegant and efficient!


