⚡JavaScript
Lesson 30 of 117
25 min
Objects, Maps & Sets
When to reach for Map vs object, destructuring, spread.
If arrays are JS's lists, objects are its everything else: bags of named values, lookup tables, config blobs, models, options arguments. There's also Map and Set, which are objects' cousins for specific jobs. Let's learn when to use which.
Object literals
js
const user = {
name: "Ada",
age: 36,
role: "admin",
};
user.name // "Ada"
user["name"] // "Ada"
user.age = 37; // properties can change
// Add new keys
user.email = "ada@example.com";
// Remove a key
delete user.age;Shorthand and computed keys
js
const name = "Ada";
const age = 36;
// Shorthand: { name, age } means { name: name, age: age }
const user = { name, age };
// Computed keys (any expression in [brackets])
const field = "role";
const u = {
[field]: "admin",
[`is_${field}`]: true,
};
// { role: "admin", is_role: true }
// Method shorthand
const obj = {
greet() { return "hi"; }, // same as greet: function () { ... }
};Object.keys / values / entries
js
const user = { name: "Ada", age: 36, role: "admin" };
Object.keys(user); // ["name", "age", "role"]
Object.values(user); // ["Ada", 36, "admin"]
Object.entries(user); // [["name","Ada"], ["age",36], ["role","admin"]]
// Loop nicely
for (const [key, value] of Object.entries(user)) {
console.log(key, "=", value);
}
// Build an object back from entries
Object.fromEntries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }Destructuring objects
js
const user = { name: "Ada", age: 36, role: "admin" };
// Pull out values
const { name, role } = user;
// Defaults
const { city = "Unknown" } = user; // city = "Unknown"
// Rename while destructuring
const { name: userName } = user; // userName = "Ada"
// Rest collects the rest
const { name: n, ...other } = user;
// n = "Ada", other = { age: 36, role: "admin" }
// Combine: nested destructuring with rename and default
const settings = { theme: { color: "dark" } };
const { theme: { color: themeColor = "light" } } = settings;Destructuring in parameters
You can destructure right in a function signature. This is how modern JS handles "options" objects:
js
function greet({ name = "stranger", greeting = "Hello" } = {}) {
return `${greeting}, ${name}!`;
}
greet(); // "Hello, stranger!"
greet({ name: "Ada" }); // "Hello, Ada!"Map: when an object isn't the right tool
Objects work as lookup tables, but they have baggage: keys are always strings or symbols, they have inherited properties, and iteration order can be weird. Map fixes all three:
js
const cache = new Map();
cache.set("a", 1);
cache.set("b", 2);
cache.get("a"); // 1
cache.has("a"); // true
cache.delete("a");
cache.size; // 1
// Keys can be any value - objects, functions, anything
const key = { id: 1 };
cache.set(key, "user data");
cache.get(key); // "user data"
// Iteration order is insertion order, always
for (const [k, v] of cache) {
console.log(k, v);
}Object vs Map
Reach for
Mapwhen keys aren't strings, when you add and remove keys often, or when you need to know the size. Reach for an object literal for fixed-shape records and config.Set: unique values
js
const tags = new Set(["a", "b", "a", "c", "b"]);
tags.size; // 3 - duplicates dropped
tags.has("a"); // true
tags.add("d");
tags.delete("a");
// Dedupe an array in one line
const unique = [...new Set([1, 2, 2, 3, 3, 3, 4])];
// [1, 2, 3, 4]
// ES2025 set methods
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
a.union(b); // Set {1, 2, 3, 4}
a.intersection(b); // Set {2, 3}
a.difference(b); // Set {1}Copying objects: shallow vs deep
js
const original = { name: "Ada", address: { city: "London" } };
// Shallow copy: top level is new, nested objects are shared
const shallow1 = { ...original };
const shallow2 = Object.assign({}, original);
shallow1.address.city = "Paris";
original.address.city; // "Paris" - they share the nested object!
// Deep copy with structuredClone (built-in, recursive)
const deep = structuredClone(original);
deep.address.city = "Berlin";
original.address.city; // unchangedstructuredClone is the modern answer
structuredClone handles dates, maps, sets, typed arrays, even cyclic references. It cannot clone functions, DOM nodes, or class instances (those become plain objects).Equality: objects compare by reference
js
{} === {} // false - different objects
[] === [] // false
const a = { x: 1 };
const b = a;
a === b; // true - same referenceFor value equality, compare fields manually or use a library. For cache keys, this is exactly why Map exists.
Try the patterns
Quiz
Quiz1 / 4
What does Object.entries({ a: 1, b: 2 }) return?
Recap
- Object literals: shorthand, computed keys, method shorthand are all standard.
Object.keys/values/entries+ destructuring is how you work with object data.- Use
Mapfor arbitrary keys and known size. UseSetfor uniqueness. - Spread is a shallow copy.
structuredCloneis a true deep copy. - Objects compare by reference, never by content.