While arrays organize data by position, objects organize data by name. Think of an object like a contact card, you do not care about the order of fields, you care about what each field represents. Objects are how JavaScript models real-world entities: a user profile, a product listing, a configuration file, an APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. response. Nearly every piece of data you work with in a web application is either an object or an array of objects.
Creating objects
Objects are created with curly braces containing key-value pairs:
const user = {
name: "Alice",
age: 25,
email: "alice@example.com",
isActive: true
};Values can be any type, strings, numbers, booleans, arrays, functions, and even other objects:
const product = {
id: 123,
name: "Laptop",
price: 999.99,
tags: ["electronics", "computers"],
specs: {
ram: "16GB",
storage: "512GB"
}
};Accessing properties
You have two ways to access object properties:
| Syntax | Example | Use when |
|---|---|---|
| Dot notation | user.name | Key is a valid identifier (most of the time) |
| Bracket notation | user["name"] | Key is dynamic, has special characters, or is in a variable |
const user = { name: "Alice", age: 25 };
// Dot notation - preferred for readability
console.log(user.name); // "Alice"
// Bracket notation - required for dynamic keys
const property = "name";
console.log(user[property]); // "Alice"
// Bracket notation - required for special characters
const data = { "first-name": "Alice" };
console.log(data["first-name"]); // "Alice"
// data.first-name would be parsed as subtraction!Accessing a property that does not exist returns undefined, it does not throw an error:
console.log(user.phone); // undefined (no error)Modifying objects
Objects are mutable, you can add, change, or remove properties at any time:
const user = { name: "Alice", age: 25 };
user.email = "alice@example.com"; // add new property
user.age = 26; // modify existing property
delete user.email; // delete property
console.log(user); // { name: "Alice", age: 26 }Even though user is declared with const, you can still change its properties. const prevents reassigning the variable itself (user = something), not changing the contents of the object it points to.
{ ...obj }) to "copy" an object, then treat it as a full clone. But spread only copies one level deep. Nested objects are still shared references. If AI generates const copy = { ...user } and then modifies copy.address.city, the original user.address.city changes too. For nested data, you need structuredClone(obj) or a library like Lodash's cloneDeep. AI also mutates function arguments directly, if a function receives an object and modifies it, the caller's data changes unexpectedly. Always treat function parameters as read-only unless the function's explicit purpose is mutation.Nested objects and arrays
Real-world data is often deeply nested. APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. responses, configuration files, and state trees all contain objects within objects:
const company = {
name: "TechCorp",
address: {
street: "123 Main St",
city: "San Francisco",
country: "USA"
},
employees: [
{ name: "Alice", role: "Developer" },
{ name: "Bob", role: "Designer" }
]
};
console.log(company.address.city); // "San Francisco"
console.log(company.employees[0].name); // "Alice"Be careful with deeply nested data, if any level is missing, you get an error:
console.log(company.ceo.name);
// TypeError: Cannot read property 'name' of undefined
// Safe access with optional chaining
console.log(company.ceo?.name); // undefined (no crash)Optional chainingWhat is optional chaining?The ?. operator that safely accesses nested properties by returning undefined instead of crashing when a value along the chain is null or undefined. (?.) is your best defense against undefined nesting. It short-circuits the entire expression and returns undefined instead of throwing.
Iterating over objects
Unlike arrays, objects do not have a .length property or built-in iteration methods like map(). Use these static methods to convert object data into arrays you can iterate:
const user = { name: "Alice", age: 25, email: "alice@example.com" };
Object.keys(user); // ["name", "age", "email"]
Object.values(user); // ["Alice", 25, "alice@example.com"]
Object.entries(user); // [["name","Alice"], ["age",25], ["email","alice@example.com"]]
// Loop over entries
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}| Method | Returns | Use case |
|---|---|---|
Object.keys(obj) | Array of key names | Loop over property names |
Object.values(obj) | Array of values | Loop over values only |
Object.entries(obj) | Array of [key, value] pairs | Loop over both |
"key" in obj | Boolean | Check if property exists |
obj.hasOwnProperty("key") | Boolean | Check own (not inherited) property |
Checking if a property exists
There are multiple ways to check whether an object has a specific property:
const user = { name: "Alice", score: 0 };
// "in" checks if the key exists (even if the value is falsy)
console.log("name" in user); // true
console.log("age" in user); // false
console.log("score" in user); // true (0 is falsy, but the key exists)
// hasOwnProperty checks only the object's own properties (not inherited)
console.log(user.hasOwnProperty("name")); // trueBe careful with truthy checks: if (user.score) would be false when score is 0, even though the property exists. Use "score" in user or user.score !== undefined instead.
Quick reference
| Operation | Syntax | Notes |
|---|---|---|
| Create | { key: value } | Key-value pairs in curly braces |
| Read (dot) | obj.key | Preferred for known keys |
| Read (bracket) | obj["key"] | Required for dynamic/special keys |
| Safe read | obj?.key | Returns undefined if obj is nullish |
| Add / Update | obj.key = value | Adds if missing, updates if exists |
| Delete | delete obj.key | Removes the property entirely |
| Copy (shallow) | { ...obj } | Only copies top-level properties |
| Copy (deep) | structuredClone(obj) | Copies nested objects too |
| Get keys | Object.keys(obj) | Returns array of key names |
| Check existence | "key" in obj | Returns boolean |