Full Stack • Java • System Design • Cloud • AI Engineering

JavaScript2026-06-17

JavaScript Objects

Master JavaScript objects with Mermaid diagrams, detailed explanations, and practical code examples covering creation, properties, methods, and advanced concepts

Objects are the fundamental building blocks of JavaScript. They store collections of key-value pairs and enable you to model real-world entities with properties and behaviors.

What is an Object?

An object is a collection of related data and functionality stored as key-value pairs. Think of it as a container that groups related information together.

// Simple object representing a person
const person = {
    name: 'John Doe',      // property
    age: 30,               // property
    greet() {              // method
        console.log(`Hello, I'm ${this.name}`);
    }
};

Object Fundamentals

graph TB
    A[JavaScript Object] --> B[Properties]
    A --> C[Methods]
    A --> D[Reference Type]
    
    B --> B1[Key-Value Pairs]
    B --> B2[Any data type]
    B --> B3[Dynamic addition]
    
    C --> C1[Functions as values]
    C --> C2[Access with this]
    C --> C3[Object behavior]
    
    D --> D1[Stored in heap]
    D --> D2[Variable holds reference]
    D --> D3[Mutable]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • Properties: Data stored as key-value pairs (name, age, email)
  • Methods: Functions that define object behavior (greet, calculate)
  • Reference Type: Variables store memory address, not the actual object
  • Dynamic: Can add, modify, or delete properties at runtime
  • Flexible: Values can be any type (primitives, objects, functions)

Creating Objects

JavaScript provides multiple ways to create objects. Each method has its use cases.

Object Creation Methods

flowchart LR
    A[Create Object] --> B[Object Literal]
    A --> C[Constructor Function]
    A --> D[Object.create]
    A --> E[Class Syntax]
    
    B --> B1[Most common]
    B --> B2[Direct syntax]
    
    C --> C1[new Object]
    C --> C2[Custom constructor]
    
    D --> D1[Prototype-based]
    D --> D2[Inheritance]
    
    E --> E1[ES6 plus syntax]
    E --> E2[Syntactic sugar]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#00BCD4

Key Points:

  • Object Literal: Simplest and most common {key: value}
  • Constructor: new Object() or custom constructors
  • Object.create(): Creates object with specific prototype
  • Class: Modern ES6+ syntax for object creation
  • Best Practice: Use object literals for simple objects

Code Examples: Creating Objects

// 1. Object Literal (Most Common)
const person = {
    name: 'John Doe',
    age: 30,
    email: '[email protected]'
};
console.log(person.name); // 'John Doe'

// 2. new Object() Constructor
const person2 = new Object();
person2.name = 'Jane Smith';
person2.age = 25;
console.log(person2.age); // 25

// 3. Constructor Function (Pre-ES6)
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.greet = function() {
        return `Hello, I'm ${this.name}`;
    };
}
const person3 = new Person('Bob', 35);
console.log(person3.greet()); // "Hello, I'm Bob"

// 4. Object.create() - Prototype-based
const personProto = {
    greet() {
        return `Hello, I'm ${this.name}`;
    }
};
const person4 = Object.create(personProto);
person4.name = 'Alice';
console.log(person4.greet()); // "Hello, I'm Alice"

// 5. ES6 Class (Modern Approach)
class PersonClass {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    greet() {
        return `Hello, I'm ${this.name}`;
    }
}
const person5 = new PersonClass('Charlie', 28);
console.log(person5.greet()); // "Hello, I'm Charlie"

Accessing Properties

You can access object properties using dot notation or bracket notation.

Property Access Methods

graph TB
    A[Access Properties] --> B[Dot Notation]
    A --> C[Bracket Notation]
    
    B --> B1[obj.property]
    B --> B2[Simple and readable]
    B --> B3[Static property names]
    
    C --> C1[obj property]
    C --> C2[Dynamic property names]
    C --> C3[Special characters allowed]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800

Key Points:

  • Dot Notation: person.name - Clean, preferred for known properties
  • Bracket Notation: person['name'] - Required for dynamic keys or special characters
  • Dynamic Access: Use brackets with variables person[key]
  • Computed Properties: Brackets allow expressions person['first' + 'Name']
  • Invalid Identifiers: Brackets needed for keys with spaces or special chars

Code Examples: Property Access

const user = {
    firstName: 'John',
    lastName: 'Doe',
    age: 30,
    'favorite color': 'blue',  // Property with space
    '123': 'numeric key'        // Numeric string key
};

// Dot Notation (preferred for simple properties)
console.log(user.firstName);  // 'John'
console.log(user.age);        // 30

// Bracket Notation (required for special cases)
console.log(user['lastName']); // 'Doe'
console.log(user['favorite color']); // 'blue' (space in key)
console.log(user['123']);     // 'numeric key'

// Dynamic Property Access
const propertyName = 'age';
console.log(user[propertyName]); // 30

// Computed Property Names
const prefix = 'first';
console.log(user[prefix + 'Name']); // 'John'

// Adding Properties
user.email = '[email protected]';  // Dot notation
user['phone'] = '555-0100';       // Bracket notation

// Updating Properties
user.age = 31;
user['firstName'] = 'Jonathan';

// Deleting Properties
delete user.phone;
console.log(user.phone); // undefined

Object Methods and this Keyword

Methods are functions stored as object properties. The this keyword refers to the object that called the method.

this Keyword Behavior

sequenceDiagram
    participant Obj as Object
    participant Method as Method
    participant This as this
    
    Obj->>Method: Call method
    Method->>This: Refers to calling object
    This->>Method: Access object properties
    Method->>Obj: Return result
    
    Note over This: this = object that called the method

Key Points:

  • Context: this refers to the object that called the method
  • Dynamic Binding: Value of this determined at call time
  • Arrow Functions: Don't have their own this, inherit from parent
  • Global Context: In global scope, this refers to window/global
  • Explicit Binding: Use call(), apply(), bind() to set this

Code Examples: Methods and this

// Object with methods
const calculator = {
    value: 0,
    
    // Regular method - has its own 'this'
    add(num) {
        this.value += num;
        return this; // Return this for method chaining
    },
    
    subtract(num) {
        this.value -= num;
        return this;
    },
    
    multiply(num) {
        this.value *= num;
        return this;
    },
    
    getValue() {
        return this.value;
    },
    
    reset() {
        this.value = 0;
        return this;
    }
};

// Using methods
calculator.add(10);
console.log(calculator.getValue()); // 10

// Method chaining
calculator
    .reset()
    .add(5)
    .multiply(3)
    .subtract(2);
console.log(calculator.getValue()); // 13

// Arrow functions vs regular functions
const person = {
    name: 'John',
    
    // Regular function - 'this' refers to person object
    regularGreet() {
        console.log(`Hello, I'm ${this.name}`);
    },
    
    // Arrow function - 'this' inherited from parent scope
    arrowGreet: () => {
        console.log(`Hello, I'm ${this.name}`); // 'this' is undefined
    },
    
    // Method that returns a function
    delayedGreet() {
        // Arrow function inherits 'this' from delayedGreet
        setTimeout(() => {
            console.log(`Hello, I'm ${this.name}`); // Works!
        }, 1000);
    }
};

person.regularGreet(); // "Hello, I'm John"
person.arrowGreet();   // "Hello, I'm undefined"
person.delayedGreet(); // "Hello, I'm John" (after 1 second)

Object References

Objects are reference types - variables store a reference (memory address) to the object, not the object itself.

Object Reference vs Value

flowchart TB
    A[Variable Assignment] --> B{Primitive or Object?}
    
    B -->|Primitive| C[Copy Value]
    C --> D[Independent Variables]
    
    B -->|Object| E[Copy Reference]
    E --> F[Shared Object]
    
    style C fill:#4CAF50
    style D fill:#4CAF50
    style E fill:#FF9800
    style F fill:#FF9800

Key Points:

  • Primitives: Copied by value, independent variables
  • Objects: Copied by reference, variables point to same object
  • Mutation: Changing object through one variable affects all references
  • Comparison: Objects compared by reference, not content
  • Cloning: Use spread {...obj} or Object.assign() for shallow copy

Code Examples: References and Comparison

// Primitive values are copied
let a = 10;
let b = a;  // b gets a copy of the value
b = 20;
console.log(a); // 10 (unchanged)
console.log(b); // 20

// Objects are referenced
const obj1 = { name: 'John', age: 30 };
const obj2 = obj1;  // obj2 references the same object

obj2.age = 31;
console.log(obj1.age); // 31 (both point to same object)
console.log(obj2.age); // 31

// Object comparison (by reference)
const person1 = { name: 'John' };
const person2 = { name: 'John' };
const person3 = person1;

console.log(person1 === person2); // false (different objects)
console.log(person1 === person3); // true (same reference)

// Shallow copy with spread operator
const original = { name: 'John', age: 30 };
const copy = { ...original };

copy.age = 31;
console.log(original.age); // 30 (independent)
console.log(copy.age);     // 31

// Shallow copy with Object.assign()
const copy2 = Object.assign({}, original);
copy2.name = 'Jane';
console.log(original.name); // 'John' (unchanged)

// Shallow copy limitation with nested objects
const user = {
    name: 'John',
    address: { city: 'NYC', zip: '10001' }
};

const userCopy = { ...user };
userCopy.address.city = 'LA';

console.log(user.address.city); // 'LA' (nested object still referenced!)
console.log(userCopy.address.city); // 'LA'

// Deep copy (fully independent)
const deepCopy = JSON.parse(JSON.stringify(user));
deepCopy.address.city = 'Chicago';
console.log(user.address.city); // 'LA' (unchanged)
console.log(deepCopy.address.city); // 'Chicago'

Object Methods

JavaScript provides built-in methods to work with objects.

Object Methods Overview

graph LR
    A[Object Methods] --> B[Object.keys]
    A --> C[Object.values]
    A --> D[Object.entries]
    A --> E[Object.assign]
    A --> F[Object.freeze]
    
    B --> B1[Returns array of keys]
    C --> C1[Returns array of values]
    D --> D1[Returns key-value pairs]
    E --> E1[Copies properties]
    F --> F1[Makes immutable]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#00BCD4
    style F fill:#F44336

Key Points:

  • Object.keys(): Get array of property names
  • Object.values(): Get array of property values
  • Object.entries(): Get array of [key, value] pairs
  • Object.assign(): Merge objects, shallow copy
  • Object.freeze(): Prevent modifications (immutable)

Code Examples: Object Methods

const person = {
    name: 'John',
    age: 30,
    city: 'New York',
    email: '[email protected]'
};

// Object.keys() - Get all property names
const keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'city', 'email']

// Iterate over keys
keys.forEach(key => {
    console.log(`${key}: ${person[key]}`);
});

// Object.values() - Get all property values
const values = Object.values(person);
console.log(values); // ['John', 30, 'New York', '[email protected]']

// Object.entries() - Get key-value pairs
const entries = Object.entries(person);
console.log(entries);
// [['name', 'John'], ['age', 30], ['city', 'New York'], ['email', '[email protected]']]

// Convert entries back to object
const newObj = Object.fromEntries(entries);
console.log(newObj); // Same as person

// Object.assign() - Merge objects
const defaults = { theme: 'light', lang: 'en', notifications: true };
const userPrefs = { theme: 'dark', lang: 'es' };
const settings = Object.assign({}, defaults, userPrefs);
console.log(settings);
// { theme: 'dark', lang: 'es', notifications: true }

// Object.freeze() - Make immutable
const config = Object.freeze({
    apiUrl: 'https://api.example.com',
    apiKey: 'secret123'
});

config.apiKey = 'newkey'; // Fails silently (throws error in strict mode)
console.log(config.apiKey); // 'secret123' (unchanged)

// Object.seal() - Prevent adding/removing properties
const user = Object.seal({ name: 'John', age: 30 });
user.age = 31;        // Allowed (modification)
user.email = 'test';  // Not allowed (addition)
delete user.name;     // Not allowed (deletion)
console.log(user);    // { name: 'John', age: 31 }

Destructuring and Optional Chaining

Modern JavaScript provides convenient syntax for extracting properties and safely accessing nested values.

Object Destructuring

flowchart LR
    A[Object] --> B[Destructuring]
    B --> C[Extract Properties]
    C --> D[Individual Variables]
    
    A --> A1[name: John, age: 30]
    D --> D1[const name, age]
    
    style A fill:#2196F3
    style B fill:#FF9800
    style C fill:#4CAF50
    style D fill:#9C27B0

Key Points:

  • Syntax: const {name, age} = person
  • Renaming: const {name: fullName} = person
  • Default Values: const {city = 'Unknown'} = person
  • Nested: const {address: {city}} = person
  • Rest: const {name, ...rest} = person

Code Examples: Destructuring and Optional Chaining

// Basic destructuring
const user = { name: 'John', age: 30, city: 'NYC', email: '[email protected]' };

const { name, age } = user;
console.log(name); // 'John'
console.log(age);  // 30

// Renaming variables
const { name: userName, age: userAge } = user;
console.log(userName); // 'John'
console.log(userAge);  // 30

// Default values
const { country = 'USA', state = 'NY' } = user;
console.log(country); // 'USA' (default)
console.log(state);   // 'NY' (default)

// Nested destructuring
const person = {
    name: 'John',
    address: {
        city: 'NYC',
        zip: '10001',
        coordinates: { lat: 40.7128, lng: -74.0060 }
    }
};

const { address: { city, zip, coordinates: { lat, lng } } } = person;
console.log(city); // 'NYC'
console.log(lat);  // 40.7128

// Rest operator
const { name: personName, ...otherDetails } = user;
console.log(personName);    // 'John'
console.log(otherDetails);  // { age: 30, city: 'NYC', email: '...' }

// Function parameter destructuring
function greet({ name, age }) {
    console.log(`Hello ${name}, you are ${age} years old`);
}
greet(user); // "Hello John, you are 30 years old"

// Optional Chaining (?.) - Safe property access
const data = {
    user: {
        profile: {
            name: 'John',
            settings: { theme: 'dark' }
        }
    }
};

// Without optional chaining (can throw error)
// console.log(data.user.profile.address.city); // Error!

// With optional chaining (returns undefined)
console.log(data?.user?.profile?.name); // 'John'
console.log(data?.user?.profile?.address?.city); // undefined (no error)
console.log(data?.user?.settings?.theme); // undefined

// Optional chaining with methods
const obj = {
    method() {
        return 'Hello';
    }
};

console.log(obj.method?.()); // 'Hello'
console.log(obj.nonExistent?.()); // undefined (no error)

// Optional chaining with arrays
const arr = [1, 2, 3];
console.log(arr?.[0]); // 1
console.log(arr?.[10]); // undefined

Best Practices

  1. Use Object Literals: Simplest and most readable for creating objects
  2. Const for Objects: Use const to prevent reassignment (object still mutable)
  3. Meaningful Keys: Use descriptive property names (camelCase convention)
  4. Avoid Mutation: Consider immutability, use spread for copies
  5. Optional Chaining: Use ?. to safely access nested properties
  6. Destructuring: Extract properties for cleaner code
  7. Method Shorthand: Use method() {} instead of method: function() {}
  8. Computed Properties: Use [expression] for dynamic keys
// Good practices example
const createUser = (name, age, email) => ({
    name,
    age,
    email,
    createdAt: new Date(),
    
    // Method shorthand
    getInfo() {
        return `${this.name} (${this.age})`;
    },
    
    // Computed property
    [`is${age >= 18 ? 'Adult' : 'Minor'}`]: true
});

const user = createUser('John', 30, '[email protected]');
console.log(user.getInfo()); // "John (30)"
console.log(user.isAdult);   // true