Objects are JavaScript's most important data structure. While arrays store ordered lists of values, objects store collections of key-value pairs, allowing you to organize related data and functionality together. From simple data storage to complex applications, objects are everywhere in JavaScript. Understanding objects is essential for becoming a proficient JavaScript developer. Let's master object fundamentals!
What Are Objects?
An object is a collection of properties, where each property is a key-value pair. The key (also called a property name) is a string, and the value can be any data type.
Think of objects like real-world entities:
- Person: name, age, email, address
- Car: brand, model, year, color
- Book: title, author, pages, price
- Product: id, name, price, inStock
Objects vs Arrays
Objects provide meaningful names for data
Array (Ordered)
// Array - ordered list
let person = ["Alice", 25, "alice@test.com"];
// Access by index (position matters)
console.log(person[0]); // "Alice"
console.log(person[1]); // 25
// What does index 1 mean?
// You need to remember position
// Adding/removing changes indices
person.push("NYC");
console.log(person[3]); // "NYC"Object (Key-Value)
// Object - key-value pairs
let person = {
name: "Alice",
age: 25,
email: "alice@test.com"
};
// Access by key (self-documenting)
console.log(person.name); // "Alice"
console.log(person.age); // 25
// Clear what each property means
// Order doesn't matter
// Adding properties is clear
person.city = "NYC";
console.log(person.city); // "NYC"Creating Objects
Object Literal (Most Common)
// Empty object
let emptyObj = {};
// Object with properties
let person = {
name: "Alice",
age: 25,
email: "alice@test.com",
isActive: true
};
console.log(person);
// { name: "Alice", age: 25, email: "alice@test.com", isActive: true }
// Properties can be any type
let product = {
id: 1, // number
name: "Laptop", // string
price: 1000, // number
inStock: true, // boolean
tags: ["electronics", "new"], // array
specs: { // nested object
ram: "16GB",
storage: "512GB"
}
};
console.log(product);Object Constructor (Less Common)
// Using Object constructor
let person = new Object();
person.name = "Alice";
person.age = 25;
console.log(person); // { name: "Alice", age: 25 }
// Using Object.create()
let template = {
greet: function() {
return "Hello!";
}
};
let person2 = Object.create(template);
person2.name = "Bob";
console.log(person2.name); // "Bob"
console.log(person2.greet()); // "Hello!"Best Practice: Use object literal syntax {} for creating objects. It's cleaner, more readable, and the most common approach.
Accessing Properties
Dot Notation (Most Common)
let person = {
name: "Alice",
age: 25,
email: "alice@test.com"
};
// Access properties with dot notation
console.log(person.name); // "Alice"
console.log(person.age); // 25
console.log(person.email); // "alice@test.com"
// Use in expressions
let greeting = "Hello, " + person.name;
console.log(greeting); // "Hello, Alice"
let nextYear = person.age + 1;
console.log(nextYear); // 26Bracket Notation
let person = {
name: "Alice",
age: 25,
"favorite color": "blue" // Property with space
};
// Access with bracket notation
console.log(person["name"]); // "Alice"
console.log(person["age"]); // 25
// Required for properties with spaces or special characters
console.log(person["favorite color"]); // "blue"
// person.favorite color // Syntax Error!
// Dynamic property access
let prop = "name";
console.log(person[prop]); // "Alice"
// With variables
let key = "age";
console.log(person[key]); // 25
// Useful in loops
let props = ["name", "age", "email"];
for (let prop of props) {
console.log(`${prop}: ${person[prop]}`);
}When to Use Each Notation
Use Dot Notation when:
- Property name is known and valid identifier
- Property name has no spaces or special characters
- You're writing the property name directly in code
Use Bracket Notation when:
- Property name has spaces or special characters
- Property name is stored in a variable
- Property name is dynamically computed
- Property name starts with a number
let user = {
name: "Alice",
"user-id": 123,
"2fa-enabled": true
};
// Dot notation (simple names)
console.log(user.name); // "Alice"
// Bracket notation (required for special chars)
console.log(user["user-id"]); // 123
console.log(user["2fa-enabled"]); // true
// Dynamic access
let propertyName = "name";
console.log(user[propertyName]); // "Alice"
// console.log(user.propertyName); // undefined (looks for "propertyName" key)Accessing Nested Properties
let user = {
name: "Alice",
address: {
street: "123 Main St",
city: "NYC",
zip: "10001"
},
contacts: {
email: "alice@test.com",
phone: "555-0123"
}
};
// Access nested properties
console.log(user.address.city); // "NYC"
console.log(user.address.street); // "123 Main St"
console.log(user.contacts.email); // "alice@test.com"
// Mix dot and bracket notation
console.log(user.address["zip"]); // "10001"
console.log(user["address"]["city"]); // "NYC"
// Deep nesting
let company = {
name: "TechCorp",
employees: {
engineering: {
frontend: {
lead: "Alice"
}
}
}
};
console.log(company.employees.engineering.frontend.lead); // "Alice"Handling Non-Existent Properties
let person = {
name: "Alice",
age: 25
};
// Accessing non-existent property returns undefined
console.log(person.email); // undefined
console.log(person.address); // undefined
// Check if property exists
if (person.email !== undefined) {
console.log("Email exists");
} else {
console.log("Email doesn't exist"); // This runs
}
// Better: use 'in' operator
if ("email" in person) {
console.log("Has email");
} else {
console.log("No email"); // This runs
}
// Optional chaining (ES2020) - safe deep access
let user = {
name: "Bob"
};
// Without optional chaining (might crash)
// console.log(user.address.city); // Error! Cannot read 'city' of undefined
// With optional chaining (safe)
console.log(user.address?.city); // undefined (no error)
console.log(user.contacts?.email); // undefined
// With nested objects
let company = {
employees: {
engineering: {}
}
};
console.log(company.employees.engineering.frontend?.lead); // undefinedModifying Properties
Updating Existing Properties
let person = {
name: "Alice",
age: 25,
email: "alice@test.com"
};
console.log(person); // { name: "Alice", age: 25, email: "alice@test.com" }
// Update properties
person.age = 26;
person.email = "alice.smith@test.com";
console.log(person); // { name: "Alice", age: 26, email: "alice.smith@test.com" }
// Update with bracket notation
person["name"] = "Alice Smith";
console.log(person.name); // "Alice Smith"
// Update based on current value
person.age = person.age + 1;
console.log(person.age); // 27
// Shorthand
person.age++;
console.log(person.age); // 28Adding New Properties
let person = {
name: "Alice",
age: 25
};
console.log(person); // { name: "Alice", age: 25 }
// Add new properties
person.email = "alice@test.com";
person.city = "NYC";
person.isActive = true;
console.log(person);
// { name: "Alice", age: 25, email: "alice@test.com", city: "NYC", isActive: true }
// Add with bracket notation
person["phone"] = "555-0123";
console.log(person.phone); // "555-0123"
// Add dynamic property
let propertyName = "country";
person[propertyName] = "USA";
console.log(person.country); // "USA"
// Add nested object
person.address = {
street: "123 Main St",
zip: "10001"
};
console.log(person.address.street); // "123 Main St"Deleting Properties
let person = {
name: "Alice",
age: 25,
email: "alice@test.com",
temp: "temporary data"
};
console.log(person);
// Delete property
delete person.temp;
console.log(person); // temp property removed
// Delete with bracket notation
delete person["email"];
console.log(person.email); // undefined
// Delete returns true if successful
let result = delete person.age;
console.log(result); // true
console.log(person); // { name: "Alice" }
// Can't delete non-existent property (returns true anyway)
console.log(delete person.notExists); // trueNote: Setting a property to undefined is NOT the same as deleting it. The property still exists with undefined as its value. Use delete to actually remove the property.
Property Shorthand and Computed Properties
Property Shorthand (ES6)
// Without shorthand
let name = "Alice";
let age = 25;
let person1 = {
name: name,
age: age
};
console.log(person1); // { name: "Alice", age: 25 }
// With shorthand (when variable name = property name)
let person2 = {
name, // Same as name: name
age // Same as age: age
};
console.log(person2); // { name: "Alice", age: 25 }
// Practical example
function createUser(name, email, role) {
return {
name, // name: name
email, // email: email
role, // role: role
createdAt: new Date()
};
}
let user = createUser("Bob", "bob@test.com", "admin");
console.log(user);Computed Property Names (ES6)
// Dynamic property names
let propertyName = "age";
let person = {
name: "Alice",
[propertyName]: 25 // Computed property name
};
console.log(person); // { name: "Alice", age: 25 }
// With expressions
let prefix = "user";
let id = 123;
let obj = {
[prefix + "_" + id]: "Alice"
};
console.log(obj); // { user_123: "Alice" }
// Practical example: creating object from array
let keys = ["name", "age", "email"];
let values = ["Alice", 25, "alice@test.com"];
let person2 = {};
keys.forEach((key, index) => {
person2[key] = values[index];
});
console.log(person2);
// { name: "Alice", age: 25, email: "alice@test.com" }
// Or with computed properties
let pairs = [["name", "Bob"], ["age", 30]];
let person3 = {};
for (let [key, value] of pairs) {
person3[key] = value;
}
console.log(person3); // { name: "Bob", age: 30 }Checking for Properties
let person = {
name: "Alice",
age: 25,
email: "alice@test.com"
};
// 1. Using 'in' operator
console.log("name" in person); // true
console.log("email" in person); // true
console.log("address" in person); // false
// 2. Using hasOwnProperty()
console.log(person.hasOwnProperty("name")); // true
console.log(person.hasOwnProperty("address")); // false
// 3. Checking for undefined (be careful!)
console.log(person.name !== undefined); // true
console.log(person.address !== undefined); // false
// Difference: 'in' vs hasOwnProperty vs undefined check
let obj = {
prop: undefined
};
console.log("prop" in obj); // true (property exists)
console.log(obj.hasOwnProperty("prop")); // true (property exists)
console.log(obj.prop !== undefined); // false (value is undefined)
// When to use each:
// - 'in': check if property exists (including inherited)
// - hasOwnProperty: check if property exists on object itself
// - undefined check: check if property has a truthy valuePractical Examples
Example 1: User Profile Manager
class UserProfile {
constructor(name, email) {
this.user = {
name: name,
email: email,
profile: {
bio: "",
avatar: null,
socialLinks: {}
},
settings: {
theme: "light",
notifications: true
},
createdAt: new Date()
};
}
// Get user info
getUserInfo() {
return {
name: this.user.name,
email: this.user.email,
memberSince: this.user.createdAt.toLocaleDateString()
};
}
// Update profile
updateProfile(updates) {
for (let key in updates) {
if (key in this.user.profile) {
this.user.profile[key] = updates[key];
}
}
}
// Add social link
addSocialLink(platform, url) {
this.user.profile.socialLinks[platform] = url;
}
// Update setting
updateSetting(setting, value) {
if (setting in this.user.settings) {
this.user.settings[setting] = value;
}
}
// Get full profile
getFullProfile() {
return this.user;
}
}
let profile = new UserProfile("Alice", "alice@test.com");
profile.updateProfile({ bio: "JavaScript developer" });
profile.addSocialLink("twitter", "@alice");
profile.updateSetting("theme", "dark");
console.log(profile.getUserInfo());
console.log(profile.getFullProfile());Example 2: Product Catalog
let catalog = {
products: {
laptop: {
id: 1,
name: "Laptop",
price: 1000,
stock: 10,
specs: {
ram: "16GB",
storage: "512GB"
}
},
mouse: {
id: 2,
name: "Mouse",
price: 25,
stock: 50
}
},
// Get product
getProduct(productKey) {
return this.products[productKey] || null;
},
// Update price
updatePrice(productKey, newPrice) {
if (productKey in this.products) {
this.products[productKey].price = newPrice;
return true;
}
return false;
},
// Update stock
updateStock(productKey, quantity) {
if (productKey in this.products) {
this.products[productKey].stock += quantity;
return true;
}
return false;
},
// Add product
addProduct(key, productData) {
this.products[key] = {
id: Object.keys(this.products).length + 1,
...productData,
stock: productData.stock || 0
};
},
// Get all products
getAllProducts() {
return Object.values(this.products);
},
// Get product names
getProductNames() {
return Object.keys(this.products);
}
};
catalog.updatePrice("laptop", 900);
catalog.updateStock("mouse", -5);
catalog.addProduct("keyboard", {
name: "Keyboard",
price: 75
});
console.log(catalog.getProduct("laptop"));
console.log(catalog.getProductNames());Object Basics Practice
Experiment with object creation and manipulation
console.log() to see your output in the console above.Key Takeaways
- Objects store key-value pairs (properties)
- Create objects using object literal syntax
{} - Use dot notation for simple property access:
obj.prop - Use bracket notation for dynamic access:
obj[prop] - Bracket notation required for names with spaces or special chars
- Access nested properties by chaining:
obj.nested.prop - Add properties by assigning:
obj.newProp = value - Delete properties with
delete obj.prop - Check property existence with
inoperator - Non-existent properties return
undefined
What's Next?
You now understand object fundamentals—how to create objects, access properties, and manipulate object data! Objects are the foundation of JavaScript programming and you'll use them constantly.
In the next lesson, we'll explore Object Methods and the 'this' Keyword—learning how to add functions to objects and understanding how this works in different contexts. This enables objects to have both data and behavior!
💪 Practice Challenge:
Before moving on, try creating:
- A book object with title, author, pages, and a nested publisher object
- A function that takes a user object and returns a formatted greeting
- A shopping cart object that stores products and can add/remove items
- A student object with grades array and a nested contact info object
- A function that safely accesses nested properties with optional chaining