LearnContact
Lesson 1855 min read

JavaScript Objects

Learn how to create, access, modify, copy, compare, iterate, destructure, merge, and work with JavaScript objects using properties, methods, nested data, computed keys, and real-world examples.

Introduction

Objects are one of the most important and widely used data structures in JavaScript. They allow related data and behavior to be grouped together using meaningful property names.

Almost every real-world JavaScript application uses objects. Users, products, orders, courses, employees, configuration settings, API responses, application state, form data, and database records are commonly represented as objects.

Unlike arrays, which organize values using numeric indexes, objects organize values using keys. These keys make data easier to understand because each value can be accessed using a meaningful name.

JavaScript objects can store primitive values, arrays, functions, other objects, and almost any other JavaScript value.

What You Will Learn
  • What objects are in JavaScript.
  • Why objects are important.
  • How to create objects.
  • How properties and values work.
  • How to access object properties.
  • The difference between dot and bracket notation.
  • How to access properties dynamically.
  • How to add properties.
  • How to modify properties.
  • How to delete properties.
  • How to check whether properties exist.
  • How object methods work.
  • How the this keyword works inside methods.
  • Why arrow functions behave differently with this.
  • How nested objects work.
  • How optional chaining works.
  • How nullish coalescing works.
  • How objects and arrays work together.
  • How property shorthand works.
  • How computed property names work.
  • How object destructuring works.
  • How to rename destructured variables.
  • How to use default destructuring values.
  • How to destructure nested objects.
  • How the object rest pattern works.
  • How to iterate through object properties.
  • How Object.keys() works.
  • How Object.values() works.
  • How Object.entries() works.
  • How Object.fromEntries() works.
  • How object references behave.
  • How to copy objects.
  • How shallow copies work.
  • How to merge objects.
  • How structuredClone() works.
  • How object comparison works.
  • How Object.freeze() works.
  • How Object.seal() works.
  • How property descriptors work.
  • How getters and setters work.
  • How to convert between objects and JSON.
  • How to use common real-world object patterns.
  • How to build a complete student management example.

What is an Object?

An object is a collection of related data stored as key-value pairs. Each key is called a property name, and the value associated with that key is called a property value.

Basic Object
const student = {
    name: 'Aarav',
    age: 22,
    course: 'JavaScript'
};

console.log(student);
Output
Object Structure
OBJECT: student

┌────────────────────────────┐
│ Property       Value       │
├────────────────────────────┤
│ name           Aarav       │
│ age            22          │
│ course         JavaScript  │
└────────────────────────────┘

Key + Value = Property

name: 'Aarav'
  │       │
  │       └── Property Value
  │
  └────────── Property Name

Why Do We Need Objects?

Without objects, related information would need to be stored in separate variables. This becomes difficult to organize and manage as applications grow.

Without an Object
const studentName = 'Aarav';
const studentAge = 22;
const studentCourse = 'JavaScript';
const studentCity = 'Mumbai';
With an Object
const student = {
    name: 'Aarav',
    age: 22,
    course: 'JavaScript',
    city: 'Mumbai'
};

console.log(student);

User Profiles

Store names, emails, roles, preferences, and account details.

Products

Represent product names, prices, categories, stock, and ratings.

Orders

Group customer, payment, delivery, and product information.

Configuration

Store application settings and feature options.

API Data

Represent structured records received from backend services.

Form Data

Group values submitted through forms.

Game Entities

Represent players, enemies, weapons, and inventory items.

Application State

Store related values that describe the current application state.

Real-World Analogy

Think of an object like an identity card. The card contains several labeled pieces of information about one person.

Identity Card Analogy
┌─────────────────────────────┐
│       STUDENT ID CARD       │
├─────────────────────────────┤
│ Name:       Aarav           │
│ Age:        22              │
│ Course:     JavaScript      │
│ City:       Mumbai          │
└─────────────────────────────┘

JavaScript Object:

{
    name: 'Aarav',
    age: 22,
    course: 'JavaScript',
    city: 'Mumbai'
}

Labels  → Property Names
Values  → Property Values
ID Card → Object

Creating Objects

JavaScript provides several ways to create objects. Object literal syntax is the most common and recommended approach for creating individual objects.

Object Literal

An object literal uses curly braces to create an object. Properties are separated by commas.

Object Literal
const product = {
    name: 'Laptop',
    price: 50000,
    inStock: true
};

console.log(product);
Output
Recommended Syntax
  • Object literals are concise.
  • They are easy to read.
  • Properties are visible directly.
  • Use object literals for most individual objects.

Object Constructor

An empty object can also be created using the Object constructor.

Object Constructor
const user = new Object();

user.name = 'Priya';
user.age = 24;

console.log(user);
Output
Object Literal vs Constructor
  • {} is shorter and easier to read.
  • new Object() creates an empty object.
  • Both approaches create ordinary objects.
  • Object literal syntax is preferred in normal code.

Object.create()

Object.create() creates a new object using another object as its prototype.

Object.create()
const person = {
    greet() {
        console.log('Hello!');
    }
};

const student =
    Object.create(person);

student.name = 'Aarav';

console.log(student.name);

student.greet();
Output

The student object does not directly contain the greet method. It inherits access to the method through its prototype.

Properties and Values

Object properties can store almost any JavaScript value, including strings, numbers, booleans, arrays, functions, and other objects.

Different Property Values
const course = {
    title: 'JavaScript',
    lessons: 27,
    free: true,
    instructor: null,
    topics: [
        'Variables',
        'Functions',
        'Objects'
    ],
    details: {
        level: 'Beginner',
        duration: '20 Hours'
    },
    start() {
        console.log(
            'Course Started'
        );
    }
};

console.log(course);

Accessing Object Properties

Object properties can be accessed using dot notation or bracket notation.

Dot Notation

Dot notation accesses a property by writing the object name, followed by a dot and the property name.

Dot Notation
const student = {
    name: 'Aarav',
    age: 22,
    course: 'JavaScript'
};

console.log(student.name);
console.log(student.age);
console.log(student.course);
Output

Bracket Notation

Bracket notation accesses a property using square brackets and a string containing the property name.

Bracket Notation
const student = {
    name: 'Aarav',
    age: 22
};

console.log(
    student['name']
);

console.log(
    student['age']
);
Output

Bracket notation is required when property names contain spaces or other characters that cannot be used with dot notation.

Property with Spaces
const student = {
    'full name': 'Aarav Sharma'
};

console.log(
    student['full name']
);
Output

Dot vs Bracket Notation

Dot vs Bracket Notation
Feature                  Dot          Bracket
----------------------------------------------------
Simple Property            Yes          Yes

Dynamic Property           No           Yes

Property with Spaces       No           Yes

Variable as Key            No           Yes

Readability                Higher       Depends

Example:
    user.name

    user['name']

Dynamic Example:
    user[propertyName]

Dynamic Property Access

Bracket notation allows a variable to determine which property should be accessed.

Dynamic Property
const user = {
    name: 'Priya',
    age: 24,
    city: 'Mumbai'
};

const propertyName = 'city';

console.log(
    user[propertyName]
);
Output
Dynamic Function
function getProperty(
    object,
    propertyName
) {
    return object[propertyName];
}

const product = {
    name: 'Laptop',
    price: 50000
};

console.log(
    getProperty(
        product,
        'price'
    )
);
Output

Adding Properties

New properties can be added after an object has been created.

Add Properties
const user = {
    name: 'Aarav'
};

user.age = 22;

user['city'] = 'Mumbai';

console.log(user);
Output

Modifying Properties

Existing properties can be updated by assigning new values.

Modify Properties
const product = {
    name: 'Laptop',
    price: 50000
};

product.price = 45000;

console.log(product);
Output
Objects are Mutable
  • Properties can be added.
  • Properties can be modified.
  • Properties can be deleted.
  • A const object can still have its contents changed.
const Object Mutation
const user = {
    name: 'Aarav'
};

user.name = 'Priya';

user.age = 24;

console.log(user);
Output

Deleting Properties

The delete operator removes a property from an object.

Delete Property
const user = {
    name: 'Aarav',
    age: 22,
    password: 'secret'
};

delete user.password;

console.log(user);
Output

Checking Properties

JavaScript provides multiple ways to check whether an object contains a property.

in Operator

The in operator checks whether a property exists in an object or anywhere in its prototype chain.

in Operator
const user = {
    name: 'Aarav',
    age: 22
};

console.log(
    'name' in user
);

console.log(
    'city' in user
);
Output

Object.hasOwn()

Object.hasOwn() checks whether a property belongs directly to the object.

Object.hasOwn()
const user = {
    name: 'Aarav',
    age: 22
};

console.log(
    Object.hasOwn(
        user,
        'name'
    )
);

console.log(
    Object.hasOwn(
        user,
        'city'
    )
);
Output

Object Methods

When a function is stored as an object property, it is called a method.

Object Method
const user = {
    name: 'Aarav',

    greet: function () {
        console.log('Hello!');
    }
};

user.greet();
Output

Method Shorthand

Modern JavaScript provides a shorter syntax for defining methods.

Method Shorthand
const user = {
    name: 'Aarav',

    greet() {
        console.log('Hello!');
    }
};

user.greet();
Output

The this Keyword

Inside a regular object method, this usually refers to the object that called the method.

this in an Object Method
const user = {
    firstName: 'Aarav',
    lastName: 'Sharma',

    getFullName() {
        return (
            this.firstName +
            ' ' +
            this.lastName
        );
    }
};

console.log(
    user.getFullName()
);
Output
this Flow
user.getFullName()
 │
 │ Method called by user
 ▼
this === user

this.firstName
     ↓
'Aarav'

this.lastName
     ↓
'Sharma'

Result:
'Aarav Sharma'

Arrow Functions in Objects

Arrow functions do not create their own this value. For methods that need the object through this, regular method syntax is usually the correct choice.

Avoid Arrow Function for this
const user = {
    name: 'Aarav',

    greet: () => {
        console.log(
            this.name
        );
    }
};

user.greet();
Typical Output
Correct Method Syntax
const user = {
    name: 'Aarav',

    greet() {
        console.log(
            this.name
        );
    }
};

user.greet();
Output
Arrow Function Warning
  • Arrow functions do not have their own this.
  • Do not use an arrow function as an object method when the method needs this.
  • Use regular method shorthand for object methods that access object properties through this.

Nested Objects

An object can contain another object as a property value.

Nested Object
const student = {
    name: 'Aarav',

    address: {
        city: 'Mumbai',
        state: 'Maharashtra',
        country: 'India'
    }
};

console.log(student);

Accessing Nested Properties

Nested Property Access
const student = {
    name: 'Aarav',

    address: {
        city: 'Mumbai',
        state: 'Maharashtra'
    }
};

console.log(
    student.address.city
);

console.log(
    student['address']['state']
);
Output

Optional Chaining

Optional chaining uses ?. to safely access nested properties. If a value before ?. is null or undefined, the expression returns undefined instead of throwing an error.

Without Optional Chaining
const user = {
    name: 'Aarav'
};

// Error if address is undefined
console.log(
    user.address.city
);
With Optional Chaining
const user = {
    name: 'Aarav'
};

console.log(
    user.address?.city
);
Output
Deep Optional Chaining
const user = {
    profile: {
        contact: {
            email:
                'aarav@example.com'
        }
    }
};

console.log(
    user.profile
        ?.contact
        ?.email
);

console.log(
    user.profile
        ?.address
        ?.city
);
Output

Nullish Coalescing

The nullish coalescing operator provides a fallback value only when the left side is null or undefined.

Optional Chaining with Fallback
const user = {
    name: 'Aarav'
};

const city =
    user.address?.city
    ?? 'Unknown City';

console.log(city);
Output

Objects with Arrays

Object properties can contain arrays.

Array Inside Object
const student = {
    name: 'Aarav',

    skills: [
        'HTML',
        'CSS',
        'JavaScript'
    ]
};

console.log(
    student.skills
);

console.log(
    student.skills[2]
);
Output

Arrays of Objects

Real-world applications frequently store multiple objects inside arrays.

Array of Objects
const products = [
    {
        id: 1,
        name: 'Laptop',
        price: 50000
    },
    {
        id: 2,
        name: 'Phone',
        price: 30000
    },
    {
        id: 3,
        name: 'Mouse',
        price: 1000
    }
];

console.log(
    products[1].name
);
Output

Property Shorthand

When a variable name and property name are identical, the property can be written using shorthand syntax.

Without Shorthand
const name = 'Aarav';
const age = 22;

const user = {
    name: name,
    age: age
};

console.log(user);
With Property Shorthand
const name = 'Aarav';
const age = 22;

const user = {
    name,
    age
};

console.log(user);
Output

Computed Property Names

Computed property names allow expressions and variables to determine property names during object creation.

Computed Property
const propertyName = 'email';

const user = {
    name: 'Aarav',

    [propertyName]:
        'aarav@example.com'
};

console.log(user);
Output

Object Destructuring

Object destructuring extracts property values into variables.

Object Destructuring
const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

const {
    name,
    age,
    city
} = user;

console.log(name);
console.log(age);
console.log(city);
Output

Renaming Destructured Variables

Rename Variables
const user = {
    name: 'Aarav',
    age: 22
};

const {
    name: userName,
    age: userAge
} = user;

console.log(userName);
console.log(userAge);
Output

Default Values

Destructuring Defaults
const user = {
    name: 'Aarav'
};

const {
    name,
    city = 'Unknown'
} = user;

console.log(name);
console.log(city);
Output

Nested Destructuring

Nested Destructuring
const user = {
    name: 'Aarav',

    address: {
        city: 'Mumbai',
        country: 'India'
    }
};

const {
    address: {
        city,
        country
    }
} = user;

console.log(city);
console.log(country);
Output

Rest Pattern

The object rest pattern collects remaining properties into a new object.

Object Rest Pattern
const user = {
    id: 1,
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

const {
    id,
    ...userDetails
} = user;

console.log(id);
console.log(userDetails);
Output

Function Parameter Destructuring

Object properties can be extracted directly in function parameters.

Parameter Destructuring
function displayUser({
    name,
    age,
    city
}) {
    console.log(
        `${name}, ${age}, ${city}`
    );
}

const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

displayUser(user);
Output

Iterating Objects

Objects are not directly iterable with for...of like arrays, but JavaScript provides several ways to process their properties.

for...in Loop

The for...in loop iterates over enumerable property names.

for...in Loop
const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

for (const key in user) {
    console.log(
        key,
        user[key]
    );
}
Output

Object.keys()

Object.keys() returns an array containing the object’s own enumerable property names.

Object.keys()
const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

const keys =
    Object.keys(user);

console.log(keys);
Output

Object.values()

Object.values() returns an array containing the object’s own enumerable property values.

Object.values()
const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

const values =
    Object.values(user);

console.log(values);
Output

Object.entries()

Object.entries() returns an array containing key-value pairs.

Object.entries()
const user = {
    name: 'Aarav',
    age: 22
};

const entries =
    Object.entries(user);

console.log(entries);
Output
Iterate Object.entries()
const user = {
    name: 'Aarav',
    age: 22
};

for (
    const [key, value]
    of Object.entries(user)
) {
    console.log(
        `${key}: ${value}`
    );
}
Output

Object.fromEntries()

Object.fromEntries() converts key-value pairs into an object.

Object.fromEntries()
const entries = [
    ['name', 'Aarav'],
    ['age', 22],
    ['city', 'Mumbai']
];

const user =
    Object.fromEntries(entries);

console.log(user);
Output

Copying Objects

Assigning an object to another variable does not create an independent copy. Both variables refer to the same object.

Object References

Shared Reference
const original = {
    name: 'Aarav'
};

const copy = original;

copy.name = 'Priya';

console.log(original.name);
console.log(copy.name);
Output
Reference Behavior
original ───────┐
                 │
                 ▼
          ┌──────────────┐
          │              │
          │ name: Priya  │
          │              │
          └──────────────┘
                 ▲
                 │
copy ────────────┘

Both variables point to
the same object.

Shallow Copies

A shallow copy creates a new outer object, but nested objects and arrays remain shared by reference.

Spread Syntax

Copy with Spread
const original = {
    name: 'Aarav',
    age: 22
};

const copy = {
    ...original
};

copy.name = 'Priya';

console.log(original.name);
console.log(copy.name);
Output
Shallow Copy Limitation
const original = {
    name: 'Aarav',

    address: {
        city: 'Mumbai'
    }
};

const copy = {
    ...original
};

copy.address.city = 'Pune';

console.log(
    original.address.city
);

console.log(
    copy.address.city
);
Output

Object.assign()

Object.assign() copies enumerable own properties from source objects into a target object.

Object.assign() Copy
const original = {
    name: 'Aarav',
    age: 22
};

const copy =
    Object.assign(
        {},
        original
    );

copy.name = 'Priya';

console.log(original);
console.log(copy);
Output

Deep Copying

A deep copy creates independent copies of nested data instead of sharing nested object references.

structuredClone()

structuredClone() creates a deep copy of many supported JavaScript values.

Deep Copy
const original = {
    name: 'Aarav',

    address: {
        city: 'Mumbai'
    },

    skills: [
        'HTML',
        'CSS'
    ]
};

const copy =
    structuredClone(original);

copy.address.city = 'Pune';

copy.skills.push(
    'JavaScript'
);

console.log(original);
console.log(copy);
Output

Merging Objects

Multiple objects can be combined using spread syntax or Object.assign(). When properties have the same name, later values overwrite earlier values.

Merge with Spread
const basicInfo = {
    name: 'Aarav',
    age: 22
};

const contactInfo = {
    email:
        'aarav@example.com',
    city: 'Mumbai'
};

const user = {
    ...basicInfo,
    ...contactInfo
};

console.log(user);
Output
Property Overwrite Order
const defaults = {
    theme: 'light',
    language: 'English'
};

const settings = {
    theme: 'dark'
};

const finalSettings = {
    ...defaults,
    ...settings
};

console.log(finalSettings);
Output

Comparing Objects

Objects are compared by reference rather than by their property contents.

Object Comparison
const first = {
    name: 'Aarav'
};

const second = {
    name: 'Aarav'
};

const third = first;

console.log(
    first === second
);

console.log(
    first === third
);
Output

Object Equality by Content

To compare object contents, the required properties must be compared or a suitable comparison function must be used.

Simple Property Comparison
const first = {
    name: 'Aarav',
    age: 22
};

const second = {
    name: 'Aarav',
    age: 22
};

const areEqual =
    first.name === second.name
    &&
    first.age === second.age;

console.log(areEqual);
Output

Freezing Objects

An object can be frozen to prevent normal additions, deletions, and modifications to its own properties.

Object.freeze()

Object.freeze()
const settings = {
    theme: 'dark',
    language: 'English'
};

Object.freeze(settings);

settings.theme = 'light';

settings.fontSize = 18;

delete settings.language;

console.log(settings);
Output
freeze() is Shallow
  • Top-level properties are protected.
  • Nested objects are not automatically deeply frozen.
  • Object.freeze() does not recursively freeze every nested value.

Sealing Objects

A sealed object prevents properties from being added or deleted, but existing writable properties can still be modified.

Object.seal()

Object.seal()
const user = {
    name: 'Aarav',
    age: 22
};

Object.seal(user);

user.age = 23;

user.city = 'Mumbai';

delete user.name;

console.log(user);
Output

Object.freeze() vs Object.seal()

Freeze vs Seal
Operation              freeze()      seal()
--------------------------------------------------
Add Property           No            No

Delete Property        No            No

Modify Property        No            Yes

Shallow                Yes           Yes

Property Descriptors

Object properties have internal attributes that control whether they can be changed, listed, or reconfigured.

Get Property Descriptor
const user = {
    name: 'Aarav'
};

const descriptor =
    Object.getOwnPropertyDescriptor(
        user,
        'name'
    );

console.log(descriptor);
Output

Object.defineProperty()

Object.defineProperty() creates or modifies a property with specific descriptor settings.

Read-Only Property
const user = {};

Object.defineProperty(
    user,
    'id',
    {
        value: 101,
        writable: false,
        enumerable: true,
        configurable: false
    }
);

console.log(user.id);
Output

Getters

A getter defines a property whose value is calculated when the property is accessed.

Getter
const user = {
    firstName: 'Aarav',
    lastName: 'Sharma',

    get fullName() {
        return (
            this.firstName +
            ' ' +
            this.lastName
        );
    }
};

console.log(
    user.fullName
);
Output

Setters

A setter runs when a value is assigned to a property.

Setter
const user = {
    firstName: '',
    lastName: '',

    set fullName(value) {
        const parts =
            value.split(' ');

        this.firstName =
            parts[0];

        this.lastName =
            parts[1] ?? '';
    }
};

user.fullName =
    'Aarav Sharma';

console.log(
    user.firstName
);

console.log(
    user.lastName
);
Output

Object Type Checking

The typeof operator returns object for ordinary objects, arrays, and null, so additional checks may be required.

typeof Values
console.log(
    typeof {}
);

console.log(
    typeof []
);

console.log(
    typeof null
);
Output

Checking Plain Objects

Plain Object Check
function isPlainObject(value) {
    return (
        typeof value === 'object'
        &&
        value !== null
        &&
        !Array.isArray(value)
    );
}

console.log(
    isPlainObject({})
);

console.log(
    isPlainObject([])
);

console.log(
    isPlainObject(null)
);
Output

Converting Objects

Objects are frequently converted to and from JSON when storing or transferring structured data.

Object to JSON

JSON.stringify()
const user = {
    name: 'Aarav',
    age: 22,
    city: 'Mumbai'
};

const json =
    JSON.stringify(user);

console.log(json);
console.log(typeof json);
Output

JSON to Object

JSON.parse()
const json =
    '{"name":"Aarav","age":22}';

const user =
    JSON.parse(json);

console.log(user);
console.log(typeof user);
Output

Common Object Patterns

Objects are frequently used for lookups, counters, grouping, indexing, configuration, and immutable updates.

Lookup Objects

A lookup object can replace repeated conditional statements when values are associated with known keys.

Lookup Object
const statusMessages = {
    pending:
        'Order is being processed.',

    shipped:
        'Order has been shipped.',

    delivered:
        'Order was delivered.',

    cancelled:
        'Order was cancelled.'
};

const status = 'shipped';

console.log(
    statusMessages[status]
);
Output

Counting Occurrences

Frequency Object
const fruits = [
    'Apple',
    'Banana',
    'Apple',
    'Mango',
    'Apple'
];

const counts = {};

for (const fruit of fruits) {
    counts[fruit] =
        (counts[fruit] ?? 0) + 1;
}

console.log(counts);
Output

Grouping Data

Group Students by Course
const students = [
    {
        name: 'Aarav',
        course: 'JavaScript'
    },
    {
        name: 'Priya',
        course: 'Java'
    },
    {
        name: 'Rohan',
        course: 'JavaScript'
    }
];

const grouped =
    students.reduce(
        function (
            result,
            student
        ) {
            const course =
                student.course;

            if (!result[course]) {
                result[course] = [];
            }

            result[course].push(
                student
            );

            return result;
        },
        {}
    );

console.log(grouped);
Output

Indexing Arrays by ID

An array of records can be transformed into an object for fast lookup by ID.

Index by ID
const users = [
    {
        id: 101,
        name: 'Aarav'
    },
    {
        id: 102,
        name: 'Priya'
    },
    {
        id: 103,
        name: 'Rohan'
    }
];

const usersById =
    users.reduce(
        function (
            result,
            user
        ) {
            result[user.id] = user;

            return result;
        },
        {}
    );

console.log(
    usersById[102]
);
Output

Updating Object Data

Spread syntax is commonly used to create an updated object without changing the original object.

Immutable Object Update
const user = {
    id: 1,
    name: 'Aarav',
    age: 22
};

const updatedUser = {
    ...user,
    age: 23
};

console.log(user);
console.log(updatedUser);
Output

Removing Object Properties

Destructuring with the rest pattern can create a new object without selected properties.

Remove Property Without Mutation
const user = {
    id: 1,
    name: 'Aarav',
    password: 'secret'
};

const {
    password,
    ...safeUser
} = user;

console.log(safeUser);
Output

Complete Object Example

The following example builds a student profile manager that uses objects for storing, displaying, updating, calculating, and managing structured data.

index.html
<div class="student-manager">
    <h2>Student Profile Manager</h2>

    <div class="student-form">
        <input
            id="nameInput"
            type="text"
            placeholder="Student name"
        >

        <input
            id="ageInput"
            type="number"
            placeholder="Age"
        >

        <input
            id="courseInput"
            type="text"
            placeholder="Course"
        >

        <input
            id="cityInput"
            type="text"
            placeholder="City"
        >

        <button id="updateButton">
            Update Profile
        </button>
    </div>

    <div id="profileCard"></div>

    <div class="student-actions">
        <button id="addSkillButton">
            Add JavaScript Skill
        </button>

        <button id="toggleStatusButton">
            Toggle Status
        </button>
    </div>
</div>
script.js
let student = {
    id: 101,

    name: 'Aarav Sharma',

    age: 22,

    course: 'Web Development',

    address: {
        city: 'Mumbai',
        country: 'India'
    },

    skills: [
        'HTML',
        'CSS'
    ],

    active: true,

    get fullName() {
        return this.name;
    },

    get skillCount() {
        return this.skills.length;
    }
};


const nameInput =
    document.getElementById(
        'nameInput'
    );

const ageInput =
    document.getElementById(
        'ageInput'
    );

const courseInput =
    document.getElementById(
        'courseInput'
    );

const cityInput =
    document.getElementById(
        'cityInput'
    );

const updateButton =
    document.getElementById(
        'updateButton'
    );

const addSkillButton =
    document.getElementById(
        'addSkillButton'
    );

const toggleStatusButton =
    document.getElementById(
        'toggleStatusButton'
    );

const profileCard =
    document.getElementById(
        'profileCard'
    );


updateButton.addEventListener(
    'click',
    updateProfile
);


addSkillButton.addEventListener(
    'click',
    addSkill
);


toggleStatusButton.addEventListener(
    'click',
    toggleStatus
);


function updateProfile() {
    const name =
        nameInput.value.trim();

    const age =
        Number(ageInput.value);

    const course =
        courseInput.value.trim();

    const city =
        cityInput.value.trim();


    student = {
        ...student,

        name:
            name || student.name,

        age:
            age > 0
                ? age
                : student.age,

        course:
            course || student.course,

        address: {
            ...student.address,

            city:
                city
                || student.address.city
        }
    };


    clearInputs();

    renderProfile();
}


function addSkill() {
    const skill = 'JavaScript';

    if (
        !student.skills.includes(
            skill
        )
    ) {
        student = {
            ...student,

            skills: [
                ...student.skills,
                skill
            ]
        };
    }

    renderProfile();
}


function toggleStatus() {
    student = {
        ...student,

        active:
            !student.active
    };

    renderProfile();
}


function clearInputs() {
    nameInput.value = '';
    ageInput.value = '';
    courseInput.value = '';
    cityInput.value = '';
}


function renderProfile() {
    profileCard.innerHTML = '';

    const title =
        document.createElement(
            'h3'
        );

    title.textContent =
        student.fullName;


    const details =
        document.createElement(
            'p'
        );

    details.textContent =
        `${student.age} years | ${student.course}`;


    const location =
        document.createElement(
            'p'
        );

    location.textContent =
        `${student.address.city}, ${student.address.country}`;


    const skills =
        document.createElement(
            'p'
        );

    skills.textContent =
        `Skills: ${student.skills.join(', ')}`;


    const skillCount =
        document.createElement(
            'p'
        );

    skillCount.textContent =
        `Total Skills: ${student.skillCount}`;


    const status =
        document.createElement(
            'p'
        );

    status.textContent =
        student.active
            ? 'Status: Active'
            : 'Status: Inactive';


    profileCard.append(
        title,
        details,
        location,
        skills,
        skillCount,
        status
    );
}


renderProfile();
Browser Output
What This Example Demonstrates
  • Creating structured objects.
  • Storing primitive values in properties.
  • Using nested objects.
  • Using arrays inside objects.
  • Using getters.
  • Accessing properties.
  • Updating object properties.
  • Using spread syntax.
  • Creating immutable updates.
  • Updating nested objects.
  • Updating nested arrays.
  • Checking array values.
  • Using object methods and derived values.
  • Using objects as application state.
  • Rendering object data into the DOM.
  • Keeping the interface synchronized with object data.

Object Processing Flow

Object Processing Flow
STRUCTURED DATA
       │
       ▼
┌────────────────────────────┐
│ CREATE OBJECT              │
│                            │
│ Object Literal             │
│ API Response               │
│ Form Data                  │
│ Application State          │
└──────────────┬─────────────┘
               │
               ▼
┌────────────────────────────┐
│ ACCESS DATA                │
│                            │
│ Dot Notation               │
│ Bracket Notation           │
│ Optional Chaining          │
└──────────────┬─────────────┘
               │
               ▼
┌────────────────────────────┐
│ PROCESS DATA               │
│                            │
│ Methods                    │
│ Destructuring              │
│ Object.keys()              │
│ Object.values()            │
│ Object.entries()           │
└──────────────┬─────────────┘
               │
               ▼
┌────────────────────────────┐
│ UPDATE DATA                │
│                            │
│ Direct Mutation            │
│ Spread Syntax              │
│ Object.assign()            │
└──────────────┬─────────────┘
               │
               ▼
┌────────────────────────────┐
│ OUTPUT                     │
│                            │
│ Display in UI              │
│ Convert to JSON            │
│ Store Data                 │
│ Send to API                │
└────────────────────────────┘

Real-World Applications

User Profiles

Store identity, contact, preferences, roles, and account details.

Products

Represent prices, stock, categories, ratings, and product details.

Orders

Group customer, payment, shipping, and item information.

Configuration

Store application settings and feature options.

API Responses

Represent structured data transferred between systems.

Forms

Group values collected from user input.

Games

Represent players, characters, enemies, weapons, and inventory.

Application State

Store related values that describe the current interface or workflow.

Authentication

Represent users, permissions, tokens, and session information.

Location Data

Store addresses, coordinates, regions, and geographical details.

Common Beginner Mistakes

Avoid These Mistakes
  • Confusing objects with arrays.
  • Trying to access object properties using numeric indexes without numeric keys.
  • Forgetting commas between object properties.
  • Using dot notation with property names that contain spaces.
  • Writing a variable name inside dot notation and expecting dynamic access.
  • Forgetting to use bracket notation for dynamic property names.
  • Accessing a property that does not exist and expecting an error instead of undefined.
  • Accessing deeply nested properties without checking intermediate values.
  • Forgetting to use optional chaining when nested data may be missing.
  • Using || when 0, false, or an empty string are valid values.
  • Confusing nullish coalescing with logical OR.
  • Assuming const makes an object immutable.
  • Reassigning a const object.
  • Accidentally modifying shared object references.
  • Assigning an object to another variable and expecting an independent copy.
  • Forgetting that spread syntax creates only a shallow copy.
  • Mutating a nested object through a shallow copy.
  • Using JSON conversion as a universal deep-copy solution.
  • Trying to clone functions with structuredClone().
  • Comparing separate objects with === and expecting property comparison.
  • Assuming objects with identical properties are automatically equal.
  • Using an arrow function as a method when this is required.
  • Assuming this always refers to the object where a function was written.
  • Calling a method without considering its calling context.
  • Using for...of directly on a plain object.
  • Using for...in without understanding inherited enumerable properties.
  • Forgetting that Object.keys() returns an array.
  • Forgetting that Object.values() returns an array.
  • Forgetting that Object.entries() returns nested key-value arrays.
  • Confusing Object.entries() with Object.fromEntries().
  • Using delete when a non-mutating update is required.
  • Forgetting that later spread properties overwrite earlier ones.
  • Placing default properties after custom properties and accidentally overwriting custom values.
  • Forgetting that Object.freeze() is shallow.
  • Assuming Object.seal() prevents modification of existing properties.
  • Confusing freeze() with seal().
  • Forgetting that getters are accessed like properties.
  • Calling a getter like a function.
  • Assigning to a getter without a setter.
  • Creating recursive getters or setters accidentally.
  • Forgetting that typeof null returns object.
  • Using typeof alone to distinguish arrays from objects.
  • Assuming every object is a plain object.
  • Using JSON.stringify() and expecting the result to remain an object.
  • Using JSON.parse() on invalid JSON.
  • Forgetting that JSON property names require double quotes.
  • Storing methods in JSON and expecting them to survive serialization.
  • Using user input directly as object keys without considering safety.
  • Using ordinary objects for every possible key-value problem without considering Map.
  • Using objects as arrays when ordered collection methods are required.
  • Using arrays as objects when meaningful named properties are required.
  • Mutating application state unexpectedly.
  • Writing deeply nested object structures that are difficult to update.
  • Ignoring missing properties in API responses.
  • Rendering untrusted object values with innerHTML.
  • Exposing sensitive object properties such as passwords.
  • Sending complete objects to clients when only selected properties are required.
  • Using object property names that are unclear or inconsistent.
  • Mixing unrelated data inside one large object.
  • Creating duplicate sources of truth across multiple objects.
Common Object Mistakes
// ❌ Wrong dynamic access
const user = {
    name: 'Aarav'
};

const key = 'name';

console.log(user.key);
// undefined


// ✅ Correct dynamic access
console.log(user[key]);
// Aarav


// ❌ Shared reference
const first = {
    name: 'Aarav'
};

const second = first;

second.name = 'Priya';

console.log(first.name);
// Priya


// ❌ Separate objects are not equal
console.log(
    { id: 1 } === { id: 1 }
);
// false


// ❌ Arrow function with this
const person = {
    name: 'Aarav',

    greet: () => {
        console.log(
            this.name
        );
    }
};


// ❌ Unsafe nested access
const customer = {};

console.log(
    customer.address.city
);
// TypeError


// ✅ Safe nested access
console.log(
    customer.address?.city
);
// undefined

Best Practices

  • Use object literal syntax for most individual objects.
  • Use meaningful property names.
  • Keep property naming consistent.
  • Use camelCase for normal JavaScript property names.
  • Use dot notation for simple known properties.
  • Use bracket notation for dynamic property access.
  • Use bracket notation when property names contain spaces or special characters.
  • Avoid property names with spaces when you control the data structure.
  • Use optional chaining for uncertain nested data.
  • Use nullish coalescing when 0, false, and empty strings are valid values.
  • Use Object.hasOwn() when checking direct ownership of a property.
  • Use method shorthand for object methods.
  • Use regular methods when this is required.
  • Do not use arrow functions as methods that depend on this.
  • Keep objects focused on related data.
  • Use nested objects when data naturally has structure.
  • Avoid unnecessary deep nesting.
  • Use arrays for ordered collections.
  • Use objects for named structured records.
  • Use arrays of objects for collections of records.
  • Use property shorthand when variable and property names match.
  • Use computed property names for dynamic keys.
  • Use destructuring when it improves readability.
  • Rename destructured variables when names conflict.
  • Use default values for optional properties.
  • Use rest syntax to separate selected and remaining properties.
  • Use function parameter destructuring for clear object-based APIs.
  • Use Object.keys() when property names are needed.
  • Use Object.values() when only values are needed.
  • Use Object.entries() when both keys and values are needed.
  • Use Object.fromEntries() to rebuild objects from entry arrays.
  • Remember that objects are reference values.
  • Use spread syntax for simple shallow copies.
  • Remember that spread syntax does not deep-clone nested data.
  • Use structuredClone() for supported deep-copy requirements.
  • Do not assume JSON serialization is a universal cloning method.
  • Use spread syntax for readable object merging.
  • Remember that later properties overwrite earlier properties.
  • Compare object properties when content equality is required.
  • Do not expect === to compare object contents.
  • Use Object.freeze() only when shallow freezing is sufficient.
  • Use Object.seal() when object shape should remain fixed but values may change.
  • Use getters for derived property values.
  • Use setters carefully for controlled assignment behavior.
  • Avoid complex hidden behavior in getters and setters.
  • Check for null when testing object types.
  • Use Array.isArray() to distinguish arrays.
  • Validate API objects before using their properties.
  • Use JSON.stringify() when converting serializable objects to JSON text.
  • Use JSON.parse() only with valid JSON.
  • Do not store sensitive values unnecessarily.
  • Remove private properties before sending data to clients.
  • Prefer immutable updates when working with application state.
  • Copy every nested level that must change during immutable updates.
  • Use unique IDs for records.
  • Use lookup objects when repeated key-based access is required.
  • Use clear helper functions for complex object transformations.
  • Avoid creating one enormous object for unrelated application data.
  • Keep a single source of truth where possible.
  • Use textContent when rendering plain object values into the DOM.
  • Test code with missing optional properties.
  • Test code with null values.
  • Test code with nested objects.
  • Test object utilities with empty objects.
  • Choose objects when named properties make data clearer.

Frequently Asked Questions

What is an object in JavaScript?

An object is a collection of related data stored as key-value pairs.

What is an object property?

A property is a key-value pair stored inside an object.

What is a property name?

It is the key used to identify a value inside an object.

What can an object store?

Objects can store strings, numbers, booleans, arrays, functions, other objects, and almost any JavaScript value.

How do I create an object?

The most common approach is object literal syntax using curly braces.

What is object literal syntax?

It creates an object directly using curly braces and key-value pairs.

What does new Object() do?

It creates a new ordinary object, usually an empty one.

What does Object.create() do?

It creates a new object using another object as its prototype.

How do I access an object property?

Use dot notation or bracket notation.

When should I use dot notation?

Use it for simple known property names.

When should I use bracket notation?

Use it for dynamic property names or property names that cannot be written with dot notation.

How do I access a property dynamically?

Store the property name in a variable and use bracket notation.

What happens when a property does not exist?

Accessing it normally returns undefined.

How do I add a property?

Assign a value to a new property using dot or bracket notation.

How do I modify a property?

Assign a new value to the existing property.

How do I delete a property?

Use the delete operator.

Can a const object be modified?

Yes. const prevents reassignment of the variable but does not make the object immutable.

How do I check whether a property exists?

Use the in operator or Object.hasOwn().

What is the difference between in and Object.hasOwn()?

in checks the object and its prototype chain, while Object.hasOwn() checks only direct properties.

What is an object method?

It is a function stored as an object property.

What does this mean inside an object method?

In a normal method call, this usually refers to the object that called the method.

Should I use arrow functions as object methods?

Not when the method needs its own this value.

What is a nested object?

It is an object stored inside another object.

How do I access nested properties?

Chain property access using dots or brackets.

What is optional chaining?

The ?. operator safely accesses properties when intermediate values may be null or undefined.

What does optional chaining return when data is missing?

It returns undefined instead of throwing an error.

What is nullish coalescing?

The ?? operator provides a fallback only when the left value is null or undefined.

Can objects contain arrays?

Yes.

Can arrays contain objects?

Yes. Arrays of objects are extremely common in real applications.

What is property shorthand?

When a variable and property have the same name, the property can be written using only that name.

What is a computed property name?

It is a property name calculated from an expression inside square brackets.

What is object destructuring?

It extracts object property values into variables.

Can destructured variables be renamed?

Yes. Use propertyName: variableName syntax.

Can destructuring provide default values?

Yes.

What does the object rest pattern do?

It collects remaining properties into a new object.

Can function parameters destructure objects?

Yes.

Can I use for...of directly on a plain object?

No. Plain objects are not directly iterable with for...of.

What does for...in do?

It iterates over enumerable property names.

What does Object.keys() return?

An array of the object’s own enumerable property names.

What does Object.values() return?

An array of the object’s own enumerable property values.

What does Object.entries() return?

An array of key-value pair arrays.

What does Object.fromEntries() do?

It converts key-value pairs into an object.

Are objects reference values?

Yes.

Does assigning an object create a copy?

No. It copies the reference.

How do I create a shallow copy?

Use spread syntax or Object.assign().

What is a shallow copy?

It creates a new outer object while nested objects remain shared references.

What does structuredClone() do?

It creates a deep copy of many supported JavaScript values.

How do I merge objects?

Use spread syntax or Object.assign().

What happens when merged objects contain the same property?

The later property value overwrites the earlier one.

Why are two identical objects not equal with ===?

Because separate objects have different references.

How do I compare objects by content?

Compare the required properties or use a suitable deep comparison function.

What does Object.freeze() do?

It prevents normal addition, deletion, and modification of the object’s own top-level properties.

Is Object.freeze() deep?

No. It is shallow.

What does Object.seal() do?

It prevents adding and deleting properties while allowing existing writable properties to change.

What is the difference between freeze() and seal()?

freeze() also prevents normal modification of existing properties, while seal() allows it.

What is a property descriptor?

It describes attributes such as value, writable, enumerable, and configurable.

What does Object.defineProperty() do?

It creates or modifies a property with controlled descriptor settings.

What is a getter?

A getter calculates a value when a property is accessed.

How do I call a getter?

Access it like a property without parentheses.

What is a setter?

A setter runs when a value is assigned to a property.

Why does typeof null return object?

It is a historical behavior of JavaScript.

How do I distinguish an array from an object?

Use Array.isArray() for arrays.

How do I check for a plain object?

Check that the value is an object, is not null, and is not an array.

How do I convert an object to JSON?

Use JSON.stringify().

How do I convert JSON text into an object?

Use JSON.parse().

Can JSON store functions?

No. JSON is a data format and does not preserve JavaScript functions.

What is a lookup object?

It maps known keys to values for fast direct access.

How can objects count occurrences?

Use values as property names and store their frequencies as property values.

How can I group array records using an object?

Use reduce() and create one object property for each group.

How can I remove a property without mutating the original object?

Use destructuring with the rest pattern.

How should I update nested objects immutably?

Copy the outer object and every nested level that needs to change.

Key Takeaways

  • Objects store related data as key-value pairs.
  • Property names identify values.
  • Object literals are the preferred creation syntax.
  • Objects can store almost any JavaScript value.
  • Dot notation accesses simple known properties.
  • Bracket notation supports dynamic property access.
  • Objects are mutable.
  • const does not make object contents immutable.
  • Properties can be added, modified, and deleted.
  • Object.hasOwn() checks direct property ownership.
  • Functions stored in objects are called methods.
  • Regular methods can access the calling object through this.
  • Arrow functions do not create their own this.
  • Objects can contain other objects.
  • Optional chaining safely accesses uncertain nested data.
  • Nullish coalescing provides fallbacks for null and undefined.
  • Objects can contain arrays.
  • Arrays can contain objects.
  • Property shorthand reduces repetition.
  • Computed property names create dynamic keys.
  • Object destructuring extracts properties into variables.
  • Destructured variables can be renamed.
  • Destructuring supports default values.
  • The rest pattern collects remaining properties.
  • Object.keys() returns property names.
  • Object.values() returns property values.
  • Object.entries() returns key-value pairs.
  • Object.fromEntries() creates objects from pairs.
  • Objects are reference values.
  • Assignment does not create an independent object copy.
  • Spread syntax creates a shallow copy.
  • Object.assign() can copy and merge objects.
  • structuredClone() creates deep copies of supported data.
  • Separate objects are compared by reference.
  • Object.freeze() prevents top-level changes.
  • Object.seal() fixes object structure while allowing value updates.
  • Getters calculate property values.
  • Setters control property assignment.
  • JSON.stringify() converts objects to JSON text.
  • JSON.parse() converts JSON text into JavaScript values.
  • Objects are essential for representing real-world structured data.

Summary

Objects are collections of related data stored as key-value pairs. They are the primary way to represent structured records in JavaScript.

Properties can be accessed using dot notation or bracket notation. Bracket notation is especially important for dynamic property access.

Objects are mutable and can contain primitive values, arrays, functions, and other objects. Functions stored inside objects are called methods.

The this keyword allows regular methods to access the object that called them, while arrow functions do not create their own this value.

Nested objects, optional chaining, nullish coalescing, arrays of objects, and computed properties allow complex real-world data to be represented safely and clearly.

Destructuring provides concise access to object properties, while Object.keys(), Object.values(), and Object.entries() make object iteration easier.

Objects are reference values. Spread syntax and Object.assign() create shallow copies, while structuredClone() can create deep copies of supported values.

Object.freeze(), Object.seal(), property descriptors, getters, and setters provide additional control over object behavior.

Mastering objects is essential because users, products, orders, settings, API responses, application state, and most structured JavaScript data are represented using objects.

Lesson 18 Completed
  • You understand what JavaScript objects are.
  • You can create objects.
  • You understand properties and values.
  • You can use dot notation.
  • You can use bracket notation.
  • You can access properties dynamically.
  • You can add properties.
  • You can modify properties.
  • You can delete properties.
  • You can check whether properties exist.
  • You can create object methods.
  • You understand the this keyword.
  • You understand arrow function behavior with this.
  • You can work with nested objects.
  • You can use optional chaining.
  • You can use nullish coalescing.
  • You can work with objects and arrays together.
  • You can use property shorthand.
  • You can create computed property names.
  • You can destructure objects.
  • You can rename destructured variables.
  • You can use destructuring defaults.
  • You can use the object rest pattern.
  • You can iterate through objects.
  • You can use Object.keys().
  • You can use Object.values().
  • You can use Object.entries().
  • You can use Object.fromEntries().
  • You understand object references.
  • You can create shallow copies.
  • You can create deep copies of supported data.
  • You can merge objects.
  • You understand object comparison.
  • You can freeze objects.
  • You can seal objects.
  • You understand property descriptors.
  • You can create getters.
  • You can create setters.
  • You can convert objects to JSON.
  • You can convert JSON into objects.
  • You can use common object-processing patterns.
  • You can build a complete student profile manager.
  • You are ready to learn the JavaScript Date object.
Next Lesson →

JavaScript Date