Topic 40 of 48 · Full Stack Essentials

JavaScript Objects

Lesson TL;DRTopic 3: JavaScript Objects 📖 15 min read · 🎯 beginner · 🧭 Prerequisites: elementdesignbasedonthepicturerequirement, iframeembedalbumsembedvideoembedmapsinputtagintroduction Why this matters Think ...
15 min read·beginner·javascript · objects · data-structures · destructuring

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 this keyword
  • Iterate over object properties with for...in and hasOwnProperty
  • 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:

  1. The object must have: name (string), grade (number), courses (array of strings), and a method promote() that increments grade by 1 and logs "<name> is now in grade <grade>".
  2. Add a nested contact object with email and phone fields.
  3. Clone the object using the spread operator and verify the clone is independent by changing name on 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, this refers to the owning object.
  • for...in combined with hasOwnProperty safely iterates only an object's own properties.
  • The spread operator ({ ...obj }) and Object.assign({}, obj) clone or merge objects shallowly — nested objects are still shared by reference.

📚 Further Reading

Like this topic? It’s one of 48 in Full Stack Essentials.

Block your seat for ₹2,500 and join the next cohort.