💡 Key Takeaways
🧱 Object Basics:** Objects store key-value pairs — use literals {} or Object.create() to define them.
🔍 Property Control:** Use defineProperty() for fine-tuned descriptors (getters, setters, read-only).
🌀 Cloning Choices:** Spread ..., Object.assign(), or structuredClone() to copy safely.
⚙️ Merge Mastery:** Combine multiple objects easily with spread syntax or deep merge helpers.
🧬 Prototype Power:** Learn how inheritance and Object.create() let you extend behavior.
🏗️ Object Creation
- Use literal
{}or constructor/class to create objects - Methods are just functions inside objects
Object.create()links a prototype
// Literal
const person = { name: 'John', age: 30 };
// Constructor
function Person(name, age) {
this.name = name;
this.age = age;
}
// Class
class PersonClass {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// Object.create()
const proto = { greet() { return 'Hi!'; } };
const user = Object.create(proto);
user.name = 'Alice';
🔑 Access & Modify Properties
- Dot and bracket notation for property access
- Optional chaining
?.prevents errors - Nullish coalescing
??provides defaults
const user = { name: 'John', address: { city: 'NYC' } };
console.log(user.name); // 'John'
console.log(user['address']); // { city: 'NYC' }
console.log(user?.address?.city); // 'NYC'
console.log(user.phone ?? 'N/A'); // 'N/A'
➕ Add & ➖ Remove
- Add or update using dot/bracket notation
deleteremoves propertiesinandhasOwnProperty()check existence
const person = { name: 'John' };
person.age = 30;
delete person.name;
console.log('age' in person); // true
console.log(person.hasOwnProperty('age')); // true
📋 Enumerate Properties
- Extract keys, values, and entries
- Use
for...infor iteration - Symbols require special handling
const obj = { a: 1, b: 2, [Symbol('id')]: 3 };
Object.keys(obj); // ['a', 'b']
Object.values(obj); // [1, 2]
Object.entries(obj); // [['a',1],['b',2]]
Object.getOwnPropertySymbols(obj); // [Symbol(id)]
🧬 Shallow Clone
- Creates a new top-level copy
- Nested objects stay referenced
const original = { name: 'John', info: { city: 'NYC' } };
const copy1 = { ...original };
const copy2 = Object.assign({}, original);
copy1.info.city = 'LA';
console.log(original.info.city); // 'LA' (shared!)
🌊 Deep Clone
- Safely copies nested data
- Works with structuredClone() or recursion
// Modern method
const deepClone = structuredClone(original);
// Recursive method
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) clone[key] = deepCopy(obj[key]);
return clone;
}
⚡ Merge Objects
- Combine with spread or
Object.assign() - Rightmost overwrites duplicates
const base = { a: 1, b: 2 };
const extra = { b: 3, c: 4 };
const merged = { ...base, ...extra };
// { a: 1, b: 3, c: 4 }
Object.assign(base, extra); // mutates base
🧩 Deep Merge
- Recursively merge nested objects
- Useful for configs and state
function deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
result[key] = deepMerge(result[key] || {}, source[key]);
} else {
result[key] = source[key];
}
}
return result;
}
const obj1 = { a: { x: 1 } };
const obj2 = { a: { y: 2 } };
deepMerge(obj1, obj2); // { a: { x:1, y:2 } }
🔄 Transform Objects
- Convert between arrays and objects
- Filter, map, or group data easily
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' }
];
// Array → Object
const map = Object.fromEntries(users.map(u => [u.id, u]));
// Object → Array
const list = Object.entries(map).map(([id, user]) => ({ id, ...user }));
🧬 Prototype & Inheritance
- Use prototypes to share behavior
- ES6
classsyntax simplifies inheritance
class Animal {
speak() { return 'sound'; }
}
class Dog extends Animal {
speak() { return 'bark'; }
}
const rex = new Dog();
rex.speak(); // 'bark'
🧠 Utilities
- Validate, compare, and inspect objects
function isObject(v) {
return v && typeof v === 'object' && !Array.isArray(v);
}
function deepEqual(a, b) {
if (a === b) return true;
if (!isObject(a) || !isObject(b)) return false;
const keys = Object.keys(a);
return keys.length === Object.keys(b).length &&
keys.every(k => deepEqual(a[k], b[k]));
}
deepEqual({x:1}, {x:1}); // true
💾 Safe JSON
- Safely stringify objects with error handling
function safeStringify(obj) {
try {
return JSON.stringify(obj, null, 2);
} catch {
return 'Serialization failed';
}
}