Objects (Plain Objects)
What are objects?
Objects are collections of key-value pairs. They let you group related data together and access it by name rather than by position (like arrays).
const person = {
name: "Alice",
age: 30,
city: "New York"
};
In JavaScript, objects are used for:
- Representing structured data (like a user, product, or configuration)
- Creating namespaces (grouping related functions)
- As maps/dictionaries (storing data you look up by key)
Note: This guide covers plain objects (also called "object literals"). We'll cover classes and object-oriented programming in the OOP guide.
Objects as key–value maps
Objects store data as properties (also called keys) with associated values:
const person = {
name: "Alice", // key: "name", value: "Alice"
age: 30, // key: "age", value: 30
isActive: true // key: "isActive", value: true
};
Each property is a key: value pair. Keys are strings (or symbols), and values can be any JavaScript type.
Dot notation vs bracket notation
You can access object properties in two ways:
Dot notation
const person = {
name: "Alice",
age: 30
};
person.name; // "Alice"
person.age; // 30
Use dot notation when: You know the property name at write-time and it's a valid identifier.
Bracket notation
const person = {
name: "Alice",
age: 30
};
person["name"]; // "Alice"
person["age"]; // 30
// Bracket notation allows variables
const key = "name";
person[key]; // "Alice"
Use bracket notation when:
- The property name is stored in a variable
- The property name contains special characters or spaces
- The property name starts with a number
const obj = {
"first name": "Alice", // Property name with space
"2nd item": "value" // Property name starting with number
};
obj["first name"]; // "Alice" (bracket notation required)
obj["2nd item"]; // "value" (bracket notation required)
Adding and removing properties
Objects are mutable, meaning you can add, modify, and remove properties after creation.
Adding properties
const person = {
name: "Alice"
};
person.age = 30; // Add new property with dot notation
person["city"] = "NYC"; // Add new property with bracket notation
person.isActive = true; // Add boolean property
console.log(person);
// { name: "Alice", age: 30, city: "NYC", isActive: true }
Modifying properties
const person = {
name: "Alice",
age: 30
};
person.age = 31; // Modify existing property
person["name"] = "Bob"; // Also works
Removing properties
Use the delete operator:
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
delete person.city; // Remove the "city" property
console.log(person); // { name: "Alice", age: 30 }
Nested objects
Objects can contain other objects (and arrays):
const person = {
name: "Alice",
age: 30,
address: {
street: "123 Main St",
city: "New York",
zipCode: "10001"
},
hobbies: ["reading", "coding"]
};
person.address.city; // "New York"
person.hobbies[0]; // "reading"
person.address.street; // "123 Main St"
You can nest objects as deeply as needed, though too much nesting can make code harder to read.
Looping over objects
There are several ways to iterate over an object's properties:
for...in loop
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
for (const key in person) {
console.log(key, person[key]);
}
// Output:
// name Alice
// age 30
// city NYC
for...in also iterates over inherited properties (from prototypes). In most cases, you'll want to use Object.keys(), Object.values(), or Object.entries() instead.
Object.keys() — get property names
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
Object.keys(person); // ["name", "age", "city"]
// Iterate over keys
for (const key of Object.keys(person)) {
console.log(key, person[key]);
}
Object.values() — get property values
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
Object.values(person); // ["Alice", 30, "NYC"]
for (const value of Object.values(person)) {
console.log(value);
}
Object.entries() — get key-value pairs
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
Object.entries(person);
// [["name", "Alice"], ["age", 30], ["city", "NYC"]]
for (const [key, value] of Object.entries(person)) {
console.log(key, value);
}
Prefer Object.keys(), Object.values(), or Object.entries() over for...in for iterating over own properties.
Objects vs arrays (when to use each)
Both objects and arrays store collections of data, but they serve different purposes:
Use objects when:
- You need to look up values by name/key
- The data has a structure with meaningful property names
- Order doesn't matter (though modern JavaScript preserves insertion order)
- You're representing a real-world entity (person, product, configuration)
Examples:
const user = {
id: 1,
name: "Alice",
email: "alice@example.com"
};
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
};
Use arrays when:
- Order matters
- You need to iterate over all elements
- You have a list of similar items
- You need array methods (map, filter, reduce)
Examples:
const scores = [95, 87, 92, 88];
const names = ["Alice", "Bob", "Charlie"];
Combining both
Objects and arrays work great together:
const users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
];
// Find user by name
const alice = users.find(user => user.name === "Alice");
// Get all names
const names = users.map(user => user.name);
Common object operations
Checking if property exists
Use the in operator or hasOwnProperty() method to check if a property exists on an object:
const person = {
name: "Alice",
age: 30
};
// Check if property exists (including undefined values)
"name" in person; // true
"city" in person; // false
// Check if property exists and is not undefined
person.name !== undefined; // true
person.city !== undefined; // false
// Using hasOwnProperty() (for own properties only)
person.hasOwnProperty("name"); // true
Getting property with default
Use the nullish coalescing operator (??) or logical OR operator (||) to provide default values when a property is missing:
const person = {
name: "Alice"
};
// If property doesn't exist, use default
const age = person.age ?? 0; // 0 (nullish coalescing)
const city = person.city || "Unknown"; // "Unknown" (logical OR)
Copying objects
Use the spread operator (...) or Object.assign() method to create a shallow copy of an object:
const original = {
name: "Alice",
age: 30
};
// Shallow copy using spread operator
const copy = { ...original };
// Shallow copy using Object.assign()
const copy2 = Object.assign({}, original);
// Note: These are shallow copies. Nested objects are still shared.
Merging objects
Use the spread operator (...) or Object.assign() method to merge multiple objects into one:
const defaults = {
theme: "light",
language: "en"
};
const userPrefs = {
theme: "dark"
};
// Merge with spread operator
const settings = { ...defaults, ...userPrefs };
// { theme: "dark", language: "en" }
// Merge with Object.assign()
const settings2 = Object.assign({}, defaults, userPrefs);
Destructuring (preview)
Use destructuring syntax to extract properties from objects into variables:
const person = {
name: "Alice",
age: 30,
city: "NYC"
};
const { name, age } = person;
console.log(name); // "Alice"
console.log(age); // 30
// With renaming
const { name: personName } = person;
console.log(personName); // "Alice"
Destructuring is a powerful feature we'll explore more in later guides.
Objects are reference types
Objects are reference types, meaning variables store a reference to the object, not the object itself:
const obj1 = { name: "Alice" };
const obj2 = obj1; // obj2 points to the same object as obj1
obj2.name = "Bob";
console.log(obj1.name); // "Bob" (both variables point to same object!)
To create a true copy, use the spread operator or Object.assign() as shown above.