Day 2 · Concept 05
Objects
Key-value containers with method support. The base unit of state in JS. Literal syntax is friendly: { name: 'Alice', age: 30 }.
1 · The literal
const user = {
name: "Alice",
age: 30,
greet() { return `hi, I'm ${this.name}`; },
};
console.log(user.name); // dot access
console.log(user["age"]); // bracket access (for dynamic keys)
console.log(user.greet());
// Add and update
user.email = "alice@example.com";
user.age = 31;
delete user.age;
console.log(Object.keys(user)); // ['name', 'greet', 'email']2 · Shorthand and computed keys
const name = "Alice", age = 30;
// Property shorthand
const user = { name, age }; // same as { name: name, age: age }
// Computed keys
const key = "score";
const result = { [key]: 100, [`${key}-band`]: "A" };
// Method shorthand
const calc = {
add(a, b) { return a + b; },
};
console.log(user, result, calc.add(2, 3));3 · Iterating objects
const counts = { apples: 3, oranges: 5, pears: 2 };
// Keys
for (const k of Object.keys(counts)) {
console.log(k);
}
// Entries — most common
for (const [k, v] of Object.entries(counts)) {
console.log(`${k} = ${v}`);
}
// Values
const total = Object.values(counts).reduce((a, b) => a + b, 0);
console.log("total:", total);4 · Object vs Map
| Object | Map |
|---|---|
| String/Symbol keys only | Any value as key (including objects) |
Has prototype keys (toString, etc.) | Clean; no inherited keys |
Object.keys(o).length | m.size |
| JSON-serialisable | Not directly |
| Optimised for fixed shape | Optimised for frequent insert/delete |
Object for fixed records and JSON; Map when keys vary widely or aren't strings.
5 · Common mistakes
- Forgetting
thisrules on methods. Arrow functions don't bindthis; declare methods withgreet() { ... }. - Comparing objects with
===. Compares references, not contents.{a:1} === {a:1}isfalse. - Mutating function parameters. Objects are passed by reference. Spread to copy:
const copy = {...obj}. - Using
for...inon arrays. Returns indexes as strings and also inherited keys. Usefor...of.
6 · When it clicks
- You destructure in the function signature instead of reading
obj.x,obj.y. - You reach for
Object.entries(...).map(...)as a default pattern. - You know when to swap to
Mapwithout thinking.
Found this useful?