JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
51: The Map Object
You've been using plain JavaScript objects as key-value stores for a while now. For most things, they're perfect. But there's a specific wall you'll eventually hit: objects only allow strings or symbols as keys. If you try to use something else, JavaScript silently coerces it into a string, and that's where things get messy.
The trap of object key coercion
Let's say we're building a small permission system. We have a few user objects, and we want to map each user to a specific access level. My first instinct—and I've made this mistake plenty of times—is to just use a standard object.
const userAdmin = { name: 'Alice' };
const userGuest = { name: 'Bob' };
const permissions = {};
permissions[userAdmin] = 'admin';
permissions[userGuest] = 'guest';
console.log(permissions[userAdmin]); // 'guest'
console.log(permissions[userGuest]); // 'guest'
Wait, what happened? Alice should be an admin. The problem is that when I used userAdmin as a key, JavaScript converted that object into a string. Since most objects stringify to "[object Object]", both Alice and Bob were stored under the exact same key. Bob effectively overwrote Alice.
Switching to a Map for real object keys
This is exactly why the Map object exists. A Map allows you to use anything as a key—functions, objects, or primitives—without any forced string conversion. Let's rewrite that permission system the right way.
const userAdmin = { name: 'Alice' };
const userGuest = { name: 'Bob' };
// Initialize a new Map
const permissions = new Map();
// We use .set(key, value) instead of assignment
permissions.set(userAdmin, 'admin');
permissions.set(userGuest, 'guest');
console.log(permissions.get(userAdmin)); // 'admin'
console.log(permissions.get(userGuest)); // 'guest'
Now it works. The Map holds a reference to the actual object memory address, not a string representation of it. I personally prefer Maps over objects whenever the keys are dynamic or aren't guaranteed to be strings.
Checking and listing our permissions
Working with Maps requires a few different methods than you're used to with objects. You can't just use permissions.length (objects don't have that either, but you know what I mean). You use the .size property.
console.log(permissions.size); // 2
// Checking if a key exists is much cleaner than 'key in obj'
if (permissions.has(userAdmin)) {
console.log('Alice is in the system!');
}
// Iterating is also more intuitive
for (const [user, role] of permissions) {
console.log(`${user.name} has the role of ${role}`);
}
One last tip: if you ever need to wipe the entire store, permissions.clear() does the trick in one line. It's a lot more efficient than manually deleting every key or reassigning the variable to a new empty object.
📋 Practical Task
Exercise: Building a Game Item Metadata Registry
You are building a game where items (like swords and shields) are objects. You need to create a Map that associates these item objects with their current "durability" value (a number). Since multiple items might have the same name, you must use the item objects themselves as the keys.
Requirements:
- Create two separate item objects:
swordandshield. - Initialize a
MapcalleditemDurability. - Add the
swordto the map with a durability of 100. - Add the
shieldto the map with a durability of 80. - Update the
sword's durability to 95 using the.set()method. - Log the current durability of the
shieldto the console using.get(). - Log the total number of items tracked in the map using the
.sizeproperty.
There are no comments for now.