Topic 3: JavaScript Objects
📖 15 min read · 🎯 beginner · 🧭 Prerequisites: element-design-based-on-the-picture-requirement, iframe-embed-albums-embed-video-embed-maps-input-tag-introduction
Why this matters
Think about how you'd describe a person — they have a name, an age, a city, maybe a job title. Right now, you'd need four separate variables just to track one person. What happens when you have ten people? Or a hundred? Things get messy fast. JavaScript objects solve this by letting you bundle all related information together under one label — the way a contact card holds everything about someone in one place. Once you understand objects, you'll see them everywhere: in API responses, in form data, in React components. They're the backbone of how JavaScript organizes the real world.
What You'll Learn
- Create objects using three different syntaxes: literal,
new Object(), and constructor functions - Access and modify object properties with dot notation and bracket notation
- Add, delete, and dynamically manage object properties
- Define and invoke object methods using the
thiskeyword - Iterate over object properties with
for...inandhasOwnProperty - Work with nested objects, destructuring, and cloning/merging patterns
The Analogy
Think of a JavaScript object as a filing cabinet in the trainer's office. The cabinet itself is the object. Each drawer is labeled — "name," "age," "city" — those labels are the keys. Inside each drawer sits a document with the actual information — "Alice," 25, "Vizag" — those are the values. You can open any drawer by its label to read or replace what's inside, add a brand-new drawer whenever you need one, or permanently remove a drawer you no longer need. Methods are like a built-in intercom on the cabinet: press a button and the cabinet does something useful with its own contents, no external instructions required.
Chapter 1: What Is an Object?
In JavaScript, an object is a collection of properties, where each property is a key-value pair. Objects let you group related data and functionality together so they travel as a single unit through your code.
There are three common ways to create an object:
1. Object Literal Syntax — the most common approach:
let person = {
name: "Alice",
age: 25,
city: "Vizag"
};
2. Using new Object() Syntax — verbose but equivalent:
let person = new Object();
person.name = "Alice";
person.age = 25;
person.city = "Vizag";
3. Using a Constructor Function — useful when you need to create many objects of the same shape:
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
let person = new Person("Alice", 25, "Vizag");
The constructor function acts like a blueprint. Each call to new Person(...) stamps out a fresh object with its own independent copy of those properties.
Chapter 2: Accessing and Modifying Object Properties
The class has two tools for getting into an object's drawers: dot notation and bracket notation.
Dot Notation — clean and readable, use it by default:
let person = {
name: "Alice",
age: 25,
city: "Vizag"
};
console.log(person.name); // Output: Alice
console.log(person.age); // Output: 25
person.age = 26;
console.log(person.age); // Output: 26
Bracket Notation — required when the key is stored in a variable, or when the key contains spaces or special characters:
console.log(person["name"]); // Output: Alice
console.log(person["age"]); // Output: 25
person["city"] = "CoderTown";
console.log(person.city); // Output: CoderTown
Both notations read and write the same underlying property. Choose dot notation for clarity, bracket notation for dynamic key access.
Chapter 3: Adding and Deleting Properties
JavaScript objects are open structures — you can add and remove properties at any time after creation, no schema required.
Adding Properties — just assign to a key that doesn't exist yet:
person.country = "Wonderland";
console.log(person.country); // Output: Wonderland
Deleting Properties — use the delete operator:
delete person.city;
console.log(person.city); // Output: undefined
After delete, reading that key returns undefined — the slot no longer exists in the object.
Chapter 4: Object Methods
A method is a function stored as a property on an object. Methods let the object carry its own behavior alongside its data.
let person = {
name: "Alice",
age: 25,
city: "Vizag",
greet: function() {
console.log("Hello, my name is " + this.name);
}
};
person.greet(); // Output: Hello, my name is Alice
Inside greet, this refers to the object the method belongs to — so this.name reaches into the same object and reads "Alice". This is what makes methods self-contained: they operate on the object's own data without needing anything passed in.
Chapter 5: Looping Through Object Properties
When you need to visit every property in an object, for...in is the tool for the job. Pairing it with hasOwnProperty ensures you only process properties that belong directly to the object, not inherited ones from the prototype chain.
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}
For the person object above, this prints each key-value pair: name: Alice, age: 25, city: Vizag, and so on. The key variable holds the property name as a string each iteration, which is why bracket notation (person[key]) is used inside the loop.
Chapter 6: Nested Objects
Objects can contain other objects as property values. This lets you model hierarchical, real-world structures — like a person who has an address, and that address has its own fields.
let person = {
name: "Alice",
age: 25,
address: {
street: "123 Main St",
city: "Vizag",
country: "Wonderland"
}
};
console.log(person.address.city); // Output: Vizag
Chain dot notation — person.address.city — to drill into nested structures. You can go as many levels deep as your data requires.
Chapter 7: Object Destructuring
Destructuring lets you unpack an object's properties into standalone variables in a single, readable line. Instead of writing let name = person.name; let age = person.age; twice over, you write it once:
let person = {
name: "Alice",
age: 25,
city: "Vizag"
};
let { name, age, city } = person;
console.log(name); // Output: Alice
console.log(age); // Output: 25
console.log(city); // Output: Vizag
The variable names on the left { name, age, city } must match the property keys in the object. Destructuring is especially useful in function parameters when a function only needs a few fields out of a larger object.
Chapter 8: Object Methods and the this Keyword
this inside a method always refers to the object that owns the method. This makes it possible to write methods that both read and mutate the object's own state.
let person = {
name: "Alice",
age: 25,
greet: function() {
console.log("Hello, my name is " + this.name);
},
updateAge: function(newAge) {
this.age = newAge;
}
};
person.greet(); // Output: Hello, my name is Alice
person.updateAge(26);
console.log(person.age); // Output: 26
updateAge takes a parameter and writes it back to this.age — directly modifying the object. No need to return a new object or pass the object back in; this provides the direct reference.
Chapter 9: Practical Example — Managing a Book Collection
The class put everything together by modeling a library. Each book is an object with title, author, and year properties. Books are stored in an array, and new ones are added with push. Finally, forEach with a template literal displays the full collection.
let book1 = {
title: "JavaScript: The Good Parts",
author: "Douglas Crockford",
year: 2008
};
let book2 = {
title: "Eloquent JavaScript",
author: "Marijn Haverbeke",
year: 2018
};
let bookCollection = [book1, book2];
// Adding a new book to the collection
let book3 = {
title: "You Don't Know JS",
author: "Kyle Simpson",
year: 2015
};
bookCollection.push(book3);
// Displaying the book collection
bookCollection.forEach(book => {
console.log(`${book.title} by ${book.author} (${book.year})`);
});
Output:
JavaScript: The Good Parts by Douglas Crockford (2008)
Eloquent JavaScript by Marijn Haverbeke (2018)
You Don't Know JS by Kyle Simpson (2015)
This pattern — objects in arrays, iterated with forEach — is the backbone of list rendering in every frontend framework the class will encounter later.
Chapter 10: Cloning and Merging Objects
Cloning an Object
A naive assignment like let clone = person does not create a copy — both variables point to the same object. To produce a true independent copy, use the spread operator or Object.assign().
let person = {
name: "Alice",
age: 25
};
// Using the spread operator
let clone1 = { ...person };
console.log(clone1); // { name: 'Alice', age: 25 }
// Using Object.assign()
let clone2 = Object.assign({}, person);
console.log(clone2); // { name: 'Alice', age: 25 }
Both produce a shallow clone: top-level properties are copied by value, but any nested objects are still shared by reference.
Merging Objects
The same two techniques work for combining multiple objects into one:
let person = {
name: "Alice",
age: 25
};
let address = {
city: "Vizag",
country: "Wonderland"
};
// Using the spread operator
let merged1 = { ...person, ...address };
console.log(merged1);
// { name: 'Alice', age: 25, city: 'Vizag', country: 'Wonderland' }
// Using Object.assign()
let merged2 = Object.assign({}, person, address);
console.log(merged2);
// { name: 'Alice', age: 25, city: 'Vizag', country: 'Wonderland' }
When two source objects share a key, the last one wins — the rightmost spread or the last argument to Object.assign() takes precedence.
flowchart LR
A[person\nname: Alice\nage: 25] --> M[Merge]
B[address\ncity: Vizag\ncountry: Wonderland] --> M
M --> C[merged\nname: Alice\nage: 25\ncity: Vizag\ncountry: Wonderland]
🧪 Try It Yourself
Task: Build a student object that tracks a learner's progress in Vizag Academy.
Requirements:
- The object must have:
name(string),grade(number),courses(array of strings), and a methodpromote()that incrementsgradeby 1 and logs"<name> is now in grade <grade>". - Add a nested
contactobject withemailandphonefields. - Clone the object using the spread operator and verify the clone is independent by changing
nameon the clone and confirming the original is unchanged.
Starter snippet:
let student = {
name: "Bob",
grade: 1,
courses: ["HTML", "CSS", "JavaScript"],
contact: {
email: "bob@example.dev",
phone: "555-0101"
},
promote: function() {
this.grade++;
console.log(`${this.name} is now in grade ${this.grade}`);
}
};
// Call promote()
student.promote(); // Bob is now in grade 2
// Clone and test independence
let studentClone = { ...student };
studentClone.name = "Clone Bob";
console.log(student.name); // Should still print: Bob
console.log(studentClone.name); // Should print: Clone Bob
Success criterion: You see Bob is now in grade 2, then Bob, then Clone Bob in the console.
🔍 Checkpoint Quiz
Q1. What is the key difference between dot notation and bracket notation when accessing object properties?
A) Dot notation is faster at runtime than bracket notation B) Bracket notation allows dynamic key access using variables; dot notation requires a literal key name C) Bracket notation only works on arrays, not plain objects D) They produce different values for the same key
Q2. What does the following code print?
let car = {
make: "Toyota",
model: "Corolla",
describe: function() {
return this.make + " " + this.model;
}
};
delete car.model;
console.log(car.describe());
A) Toyota Corolla
B) Toyota undefined
C) A TypeError is thrown
D) undefined undefined
Q3. Given the code below, what does console.log(original.city) print after the merge?
let original = { name: "Alice", city: "Vizag" };
let update = { city: "CoderTown", country: "Wonderland" };
let merged = { ...original, ...update };
original.city = "OldTown";
console.log(merged.city);
A) Vizag
B) CoderTown
C) OldTown
D) undefined
Q4. How would you loop through every property of a config object and print only those properties that belong directly to config (not inherited)?
A) Use for (let key of config) without any guard
B) Use Object.keys(config).forEach(key => console.log(key, config[key]))
C) Use for (let key in config) { if (config.hasOwnProperty(key)) { ... } }
D) Both B and C are correct approaches
A1. B — Bracket notation accepts any expression as the key (obj[variable]), while dot notation requires you to write the literal property name in source code.
A2. B — delete car.model removes the property, so this.model inside describe resolves to undefined. The method still runs; it just concatenates "Toyota" with "undefined".
A3. B — merged.city was set to "CoderTown" at merge time (the rightmost spread wins). Later changing original.city has no effect on merged because the spread operator copies primitive values by value, not by reference.
A4. D — Both are correct. Object.keys() automatically returns only own enumerable properties, so no guard is needed. The for...in + hasOwnProperty pattern achieves the same result. Either is acceptable; Object.keys is generally preferred in modern code for clarity.
🪞 Recap
- A JavaScript object is a collection of key-value pairs that groups related data and behavior under one name.
- Properties are read and written with dot notation (
obj.key) or bracket notation (obj["key"]); bracket notation is required when the key is dynamic. - Methods are functions stored as object properties; inside them,
thisrefers to the owning object. for...incombined withhasOwnPropertysafely iterates only an object's own properties.- The spread operator (
{ ...obj }) andObject.assign({}, obj)clone or merge objects shallowly — nested objects are still shared by reference.
📚 Further Reading
- MDN: Working with Objects — the source of truth for object syntax, methods, and the prototype chain
- MDN: Destructuring Assignment — complete reference for both object and array destructuring
- Eloquent JavaScript, Chapter 4: Data Structures — Marijn Haverbeke's approachable deep-dive into objects and arrays
- ⬅️ Previous: JavaScript Basics
- ➡️ Next: PHP with Select, Fetch