Module 7: Objects
Objects are the fundamental data structure in JavaScript for storing collections of key-value pairs and complex entities.
1. Creating Objects
1.1 Object Literals
const emptyObject = {};
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
1.2 Object Constructor
const user = new Object();
user.name = 'John';
user.age = 30;
1.3 Object.create()
const personPrototype = {
greet() {
return `Hello, I'm ${this.name}`;
}
};
const user = Object.create(personPrototype);
user.name = 'John';
console.log(user.greet()); // Hello, I'm John
Best Practice
Prefer object literals {} for creating objects.
2. Accessing Properties
2.1 Dot Notation
const user = { name: 'John', age: 30 };
user.name; // 'John'
user.age; // 30
2.2 Bracket Notation
const user = { name: 'John', age: 30 };
user['name']; // 'John'
user['age']; // 30
// Dynamic property access
const prop = 'name';
user[prop]; // 'John'
// Property names with spaces or special chars
const obj = { 'first-name': 'John' };
obj['first-name']; // 'John'
2.3 Optional Chaining (ES2020)
const user = {
name: 'John',
address: {
city: 'New York'
}
};
user?.address?.city; // 'New York'
user?.address?.zip; // undefined (no error)
user?.contact?.phone; // undefined (no error)
3. Adding & Modifying Properties
const user = { name: 'John' };
// Add property
user.age = 30;
user['email'] = 'john@example.com';
// Modify property
user.name = 'Jane';
// Computed property names (ES6)
const propName = 'role';
const user2 = {
name: 'John',
[propName]: 'admin'
};
4. Deleting Properties
const user = {
name: 'John',
age: 30,
temp: 'value'
};
delete user.temp; // true
delete user.nonexistent; // true (no error)
// Set to undefined (not recommended)
user.age = undefined; // Property still exists
5. Checking Properties
const user = { name: 'John', age: 30 };
// in operator
'name' in user; // true
'email' in user; // false
// hasOwnProperty()
user.hasOwnProperty('name'); // true
user.hasOwnProperty('toString'); // false (inherited)
// Check for undefined
user.name !== undefined; // true
6. Iterating Over Objects
6.1 for...in
const user = { name: 'John', age: 30, city: 'New York' };
for (const key in user) {
console.log(key, user[key]);
}
6.2 Object.keys()
const keys = Object.keys(user); // ['name', 'age', 'city']
keys.forEach(key => {
console.log(key, user[key]);
});
6.3 Object.values()
const values = Object.values(user); // ['John', 30, 'New York']
6.4 Object.entries()
const entries = Object.entries(user);
// [['name', 'John'], ['age', 30], ['city', 'New York']]
for (const [key, value] of entries) {
console.log(key, value);
}
7. Object Methods
const calculator = {
value: 0,
add(n) {
this.value += n;
return this;
},
subtract(n) {
this.value -= n;
return this;
},
multiply(n) {
this.value *= n;
return this;
},
getValue() {
return this.value;
}
};
// Method chaining
calculator.add(5).multiply(2).subtract(3).getValue(); // 7
8. Shorthand Properties & Methods (ES6)
const name = 'John';
const age = 30;
// Old way
const user1 = {
name: name,
age: age
};
// Shorthand
const user2 = { name, age };
// Method shorthand
const obj = {
// Old way
greet: function() {
return 'Hello';
},
// Shorthand
hello() {
return 'Hello';
}
};
9. Object Destructuring (ES6)
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
// Basic destructuring
const { name, age } = user;
// Rename variables
const { name: userName, age: userAge } = user;
// Default values
const { name, role = 'user' } = user;
// Rest operator
const { name, ...rest } = user;
// rest = { age: 30, email: 'john@example.com' }
// Nested destructuring
const user2 = {
name: 'John',
address: {
city: 'New York',
zip: '10001'
}
};
const { address: { city, zip } } = user2;
10. Copying Objects
10.1 Shallow Copy
const original = { a: 1, b: 2 };
// Spread operator
const copy1 = { ...original };
// Object.assign()
const copy2 = Object.assign({}, original);
// Add properties while copying
const copy3 = { ...original, c: 3 };
10.2 Deep Copy
const original = {
name: 'John',
address: { city: 'New York' }
};
// JSON method (limitations: no functions, dates, undefined)
const deepCopy = JSON.parse(JSON.stringify(original));
// structuredClone (modern)
const deepCopy2 = structuredClone(original);
// Manual deep clone
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
11. Merging Objects
const defaults = { theme: 'light', language: 'en' };
const userSettings = { theme: 'dark' };
// Spread operator (later properties override)
const settings = { ...defaults, ...userSettings };
// { theme: 'dark', language: 'en' }
// Object.assign()
const settings2 = Object.assign({}, defaults, userSettings);
12. Object Property Descriptors
const user = {};
Object.defineProperty(user, 'name', {
value: 'John',
writable: false, // Cannot be changed
enumerable: true, // Shows in loops
configurable: false // Cannot be deleted or reconfigured
});
// Get descriptor
const descriptor = Object.getOwnPropertyDescriptor(user, 'name');
// Define multiple properties
Object.defineProperties(user, {
age: { value: 30, writable: true },
email: { value: 'john@example.com', writable: true }
});
13. Getters and Setters
const user = {
firstName: 'John',
lastName: 'Doe',
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
set fullName(value) {
[this.firstName, this.lastName] = value.split(' ');
}
};
user.fullName; // 'John Doe'
user.fullName = 'Jane Smith';
user.firstName; // 'Jane'
14. Object.freeze() & Object.seal()
// freeze - cannot add, delete, or modify properties
const user = Object.freeze({ name: 'John' });
user.name = 'Jane'; // Silently fails (strict mode: error)
user.age = 30; // Silently fails
// seal - cannot add or delete, but can modify
const user2 = Object.seal({ name: 'John' });
user2.name = 'Jane'; // ✅ Works
user2.age = 30; // ❌ Fails
// Check if frozen/sealed
Object.isFrozen(user); // true
Object.isSealed(user2); // true
15. this Keyword
const user = {
name: 'John',
greet() {
console.log(`Hello, I'm ${this.name}`);
},
greetArrow: () => {
console.log(`Hello, I'm ${this.name}`); // ❌ undefined
}
};
user.greet(); // Works: this = user
const greetFn = user.greet;
greetFn(); // ❌ this = undefined (strict mode)
// Bind this
const boundGreet = user.greet.bind(user);
boundGreet(); // Works
16. Object Comparison
// Objects are compared by reference
const obj1 = { a: 1 };
const obj2 = { a: 1 };
const obj3 = obj1;
obj1 === obj2; // false (different references)
obj1 === obj3; // true (same reference)
// Deep equality (manual)
function deepEqual(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (const key of keys1) {
const val1 = obj1[key];
const val2 = obj2[key];
const areObjects = typeof val1 === 'object' && typeof val2 === 'object';
if (areObjects) {
if (!deepEqual(val1, val2)) return false;
} else if (val1 !== val2) {
return false;
}
}
return true;
}
Summary
In this module, you learned:
- ✅ Creating and accessing object properties
- ✅ Object methods and this keyword
- ✅ Destructuring and shorthand syntax
- ✅ Copying and merging objects
- ✅ Property descriptors, getters, and setters
- ✅ Object.freeze() and Object.seal()
- ✅ Iterating over objects
- ✅ Object comparison
Next Steps
In Module 8, you'll learn about Strings – essential for text manipulation.
Practice Exercises
- Create a user object with nested address
- Implement object destructuring in function parameters
- Build a calculator object with method chaining
- Deep clone an object without JSON methods
- Create getters and setters for computed properties
- Implement a function to merge multiple objects
- Use Object.entries() to transform an object
- Compare two objects for deep equality