Objects are collections of key-value pairs that store structured data. They represent real-world entities and are fundamental to JavaScript programming.
let obj = {
name: "John",
age: 26,
isMale: true,
city: "New York",
};let obj = new Object();
obj.name = "John";
obj.age = 26;let obj = Object.create(null); // Object with no prototype
obj.name = "John";- Keys are always converted to strings internally
- Can use numbers, booleans, but they become strings
- Can use variables as keys with computed properties
let obj = {
"1": "number key",
"true": "boolean key",
"name": "string key"
};
// All of these access the same property:
console.log(obj[1]); // "number key"
console.log(obj["1"]); // "number key"
console.log(obj.1); // ❌ SyntaxError
console.log(obj[true]); // "boolean key"
console.log(obj["true"]); // "boolean key"
console.log(obj.true); // "boolean key"- For fixed key names (literal keys)
- Only works with valid identifier names
let user = {
name: "John",
age: 30,
};
console.log(user.name); // "John"
console.log(user.age); // 30- For dynamic or multi-word keys
- When key is stored in a variable
let user = {
name: "John",
"full name": "John Doe",
age: 30,
};
// Multi-word keys
console.log(user["full name"]); // "John Doe"
// Dynamic keys
let property = "name";
console.log(user[property]); // "John"
// This won't work with dot notation:
// console.log(user.property); // undefined (looks for literal "property" key)Use variables as keys when creating objects:
let role = "admin";
let level = "senior";
let user = {
name: "John",
[role]: "value", // "admin": "value"
[level + "Developer"]: true, // "seniorDeveloper": true
};
console.log(user.admin); // "value"
console.log(user.seniorDeveloper); // trueExtract properties into variables:
let user = { name: "John", age: 25, city: "NYC" };
let { name, age } = user;
console.log(name); // "John"
console.log(age); // 25let user = { name: "Navneet", age: 21 };
let { name: userName, age: userAge } = user;
console.log(userName); // "Navneet"
console.log(userAge); // 21let user = { name: "John" };
let { name, age = 25, city = "Unknown" } = user;
console.log(name); // "John"
console.log(age); // 25 (default)
console.log(city); // "Unknown" (default)let user = {
name: "Amit",
address: {
city: "Delhi",
pincode: 110001,
location: {
lat: 28.6139,
lng: 77.209,
},
},
};
// Access nested properties
console.log(user.address.city); // "Delhi"
console.log(user.address.location.lat); // 28.6139
// Destructure nested objects
let {
address: { city, pincode },
} = user;
console.log(city); // "Delhi"
console.log(pincode); // 110001
let {
address: {
location: { lat, lng },
},
} = user;
console.log(lat, lng); // 28.6139 77.2090let user = { name: "John", age: 30, city: "NYC" };
for (let key in user) {
console.log(`${key}: ${user[key]}`);
// Note: Use bracket notation because key is a variable
}
// name: John
// age: 30
// city: NYClet user = { name: "John", age: 30, city: "NYC" };
// Get all keys
let keys = Object.keys(user);
console.log(keys); // ["name", "age", "city"]
// Get all values
let values = Object.values(user);
console.log(values); // ["John", 30, "NYC"]
// Get key-value pairs
let entries = Object.entries(user);
console.log(entries); // [["name", "John"], ["age", 30], ["city", "NYC"]]
// Iterate over entries
Object.entries(user).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});let original = { name: "John", age: 30 };
let copy = { ...original };
copy.name = "Jane";
console.log(original.name); // "John" (unchanged)
console.log(copy.name); // "Jane"let original = { name: "John", age: 30 };
let copy = Object.assign({}, original);
// Can also add new properties
let copyWithExtras = Object.assign({ role: "admin" }, original);
console.log(copyWithExtras); // { role: "admin", name: "John", age: 30 }let user = {
name: "John",
address: {
city: "NYC",
zipcode: "10001",
},
};
let shallowCopy = { ...user };
shallowCopy.address.city = "LA";
console.log(user.address.city); // "LA" (original changed!)
// The nested object is still a referencelet user = {
name: "John",
address: {
city: "NYC",
zipcode: "10001",
},
};
// Method 1: JSON (limitations: no functions, undefined, dates become strings)
let deepCopy = JSON.parse(JSON.stringify(user));
deepCopy.address.city = "LA";
console.log(user.address.city); // "NYC" (unchanged)
// Method 2: structuredClone (modern browsers)
let deepCopy2 = structuredClone(user);Safely access nested properties without errors:
let user = {
name: "John",
address: {
city: "NYC",
},
};
// Without optional chaining (throws error if address doesn't exist)
// console.log(user.address.street.name); // ❌ Error if street is undefined
// With optional chaining
console.log(user?.address?.street?.name); // undefined (no error)
console.log(user?.address?.city); // "NYC"
console.log(user?.phone?.number); // undefined
// Works with methods too
user?.someMethod?.(); // Only calls if someMethod existslet calculator = {
a: 10,
b: 5,
add: function () {
return this.a + this.b;
},
// Arrow functions don't have their own 'this'
multiply: () => {
return this.a * this.b; // 'this' refers to global object
},
// Method shorthand (ES6)
subtract() {
return this.a - this.b;
},
};
console.log(calculator.add()); // 15
console.log(calculator.subtract()); // 5
console.log(calculator.multiply()); // NaN (this is not calculator)Control how properties behave:
let user = {};
Object.defineProperty(user, "name", {
value: "John",
writable: false, // Cannot be changed
enumerable: true, // Shows in for...in
configurable: false, // Cannot be deleted or reconfigured
});
user.name = "Jane"; // Silently fails (or throws in strict mode)
console.log(user.name); // "John"
// Get property descriptor
let descriptor = Object.getOwnPropertyDescriptor(user, "name");
console.log(descriptor);
// { value: "John", writable: false, enumerable: true, configurable: false }let user = { name: "John", age: 30 };
Object.freeze(user);
user.name = "Jane"; // Silently fails
user.city = "NYC"; // Silently fails
delete user.age; // Silently fails
console.log(user); // { name: "John", age: 30 } (unchanged)let user = { name: "John", age: 30 };
Object.seal(user);
user.name = "Jane"; // ✅ Works (can modify existing)
user.city = "NYC"; // ❌ Fails (cannot add new)
delete user.age; // ❌ Fails (cannot delete)
console.log(user); // { name: "Jane", age: 30 }let user = { name: "John", age: 30 };
Object.preventExtensions(user);
user.name = "Jane"; // ✅ Works
user.city = "NYC"; // ❌ Fails (cannot add new)
delete user.age; // ✅ Works
console.log(user); // { name: "Jane" }function createUser(name, age) {
return {
name: name,
age: age,
greet() {
return `Hello, I'm ${this.name}`;
},
};
}
let user1 = createUser("John", 30);
let user2 = createUser("Jane", 25);let userRoles = {
john: "admin",
jane: "user",
bob: "moderator",
};
// Check if key exists
if ("john" in userRoles) {
console.log("John has a role");
}
// Better to use Map for this purpose in modern JS
let roleMap = new Map([
["john", "admin"],
["jane", "user"],
]);- Use object literal syntax for creating objects
- Use destructuring to extract multiple properties
- Use meaningful property names that describe the data
- Use optional chaining to safely access nested properties
- Understand shallow vs deep copying implications
- Use
constfor objects that won't be reassigned - Prefer dot notation when possible for better readability
- Use Object.freeze() for truly immutable objects
- Consider using Map for key-value collections with dynamic keys
- Use method shorthand for cleaner object method definitions