Objects

Understand how to create objects using object literals, work with properties and methods, use both dot and bracket notation, use computed property names, and work with nested objects.

An object is a collection of key-value pairs, used to represent a single structured "thing" with named properties — a user, a product, a configuration, a coordinate. Where an array is best for an ordered list, an object is best when each piece of data has a meaningful name rather than just a position.

Object literals

The most common way to create an object is an object literal: curly braces containing comma-separated key: value pairs, for example const user = { name: "Ada", age: 28 }. Keys are usually written as plain identifiers or strings, and values can be any type — strings, numbers, booleans, arrays, functions, even other objects.

Object literals are by far the most widely used object-creation syntax in JavaScript, far more common than new Object() or classes for simple data structures.

Properties and methods

A key-value pair in an object is called a property. When the value of a property is a function, it's called a method, and it can be called using dot notation, for example user.greet(). Inside a method, the special this keyword refers to the object the method was called on, letting the method access that object's own other properties.

Object property values can be updated at any time by assigning to them again, and new properties can be added to an existing object simply by assigning to a key that doesn't exist yet — JavaScript objects are dynamic; their shape is not fixed after creation.

Dot notation vs bracket notation

Dot notation (object.property) is the shorter, more common way to access a property, but it only works when the property name is a valid identifier known at the time you're writing the code — it can't contain spaces, start with a number, or be a dynamic value.

Bracket notation (object["property"]) works with any string, including ones with spaces or special characters, and — crucially — it accepts a variable or expression instead of a literal name, which makes it the only option when the property name is computed at runtime, for example object[someVariable].

Computed properties

Inside an object literal, you can use square brackets around an expression as a key to compute the property name dynamically at the moment the object is created, for example { ["key" + suffix]: value }. This is called a computed property name, and it's especially useful when building objects whose key names come from a variable rather than being hardcoded.

Without computed property syntax, you would have to create the object first and then use bracket-notation assignment afterward in a separate line — computed properties let you do it in one step, inline in the literal.

Nested objects

Because an object's values can be anything, including other objects, you can build nested structures to represent hierarchical or grouped data — for example a user object containing an address object, which itself contains city and zip properties.

Accessing deeply nested properties chains dot or bracket notation: user.address.city. If any link in that chain is undefined, accessing a property on it throws a TypeError ("Cannot read properties of undefined"), which is why optional chaining (user.address?.city) is commonly used with uncertain nested data.

Object literal, properties, and notation

greet() { ... } inside the object literal is method shorthand — equivalent to greet: function() { ... }. this inside greet() refers to user, because that's the object the method was called on. Bracket notation is required whenever the property name is stored in a variable, as with user[key].

const user = {
  name: "Ada",
  age: 28,
  isAdmin: false,
  greet() {
    return `Hi, I'm ${this.name}`;
  }
};

console.log(user.name);        // dot notation
console.log(user["age"]);      // bracket notation

const key = "isAdmin";
console.log(user[key]);        // bracket notation with a variable

user.email = "[email protected]"; // add a new property
console.log(user.greet());

Code Examples

This creates a simple object literal and reads two of its properties, one with dot notation and one with bracket notation, then updates the price property directly. Expected result: Wireless Mouse 24.99 19.99 product.price = 19.99; reassigns an existing property's value.

The computed property [field]: value lets createProfile build an object whose second key name is decided by whatever string is passed in as field, rather than being fixed in the code. Expected result: { name: 'Unknown', country: 'Kenya' } { name: 'Unknown', language: 'Swahili' }

[field]: value uses the value of the field parameter as the actual property key name.

employee has a nested department object, which itself has a nested location object. Reading employee.department.location.city chains three dot-notation lookups. The greet() method uses this to reach both its own name and its nested department's properties. Mutating a deeply nested property (building) still works by chaining the same path down to the assignment. Expected result: Nairobi Grace works in Engineering at Nairobi HQ-3 employee.department.location.building = "HQ-3"; mutates a property three levels deep inside the object.

const product = {
  title: "Wireless Mouse",
  price: 24.99,
  inStock: true
};

console.log(product.title);
console.log(product["price"]);
product.price = 19.99;
console.log(product.price);
function createProfile(field, value) {
  return {
    name: "Unknown",
    [field]: value // computed property name
  };
}

const profile1 = createProfile("country", "Kenya");
const profile2 = createProfile("language", "Swahili");

console.log(profile1);
console.log(profile2);
const employee = {
  name: "Grace",
  department: {
    name: "Engineering",
    location: {
      city: "Nairobi",
      building: "HQ-2"
    }
  },
  greet() {
    return `${this.name} works in ${this.department.name} at ${this.department.location.city}`;
  }
};

console.log(employee.department.location.city);
console.log(employee.greet());

employee.department.location.building = "HQ-3";
console.log(employee.department.location.building);

Object structure and nesting

Each dot in a chained property access moves one level deeper into a nested object; if any link in the chain is missing, the next access throws a TypeError.

employee
 ├── name: "Grace"
 ├── department
 │      ├── name: "Engineering"
 │      └── location
 │             ├── city: "Nairobi"
 │             └── building: "HQ-2"
 └── greet()  ← method, uses `this` to reach the properties above

employee.department.location.city
   └────┬────┘ └────┬────┘ └─┬─┘
     object      object     value
    (level 0)   (level 1)  (level 2)

Important Rules

Object literals ({ key: value }) are the standard way to create objects for structured data.

Dot notation requires a literal, valid identifier known when writing the code; bracket notation accepts any string, including one stored in a variable.

A method is simply a property whose value is a function; this inside a method refers to the object the method was called on.

Computed property names ([expr]: value) let you set a key name dynamically inside an object literal.

Objects can be nested arbitrarily deep, and property access chains (a.b.c) walk down through each level in order.

Where this shows up

Objects are the primary way JSON data from APIs is represented in JavaScript — a response from a web server (user profiles, product listings, configuration settings) almost always arrives as a nested object structure. Nearly every function that returns more than one related value returns an object, and nearly every configuration option (from library settings to component props) is passed as an object.

const field = "score"; const player = { field: 100 }; console.log(player.score); // undefined const field = "score"; const player = { [field]: 100 }; console.log(player.score); // 100

Without the square brackets, field is treated as a literal key name "field", not evaluated as a variable — so the object ends up with a property literally called field, not score. Computed property syntax [field] is required to use the variable's value as the key.

[Multiple Choice] Why would you use bracket notation instead of dot notation to access an object property? A. Bracket notation is always faster B. Bracket notation lets you use a property name stored in a variable, or a name with spaces/special characters C. Dot notation cannot access nested objects D. There is no difference; they are interchangeable in every situation

B. Bracket notation lets you use a property name stored in a variable, or a name with spaces/special characters — Bracket notation accepts any expression, including a variable holding the key name, or a string with spaces/special characters that would be invalid as a plain identifier. Dot notation only works with a literal, valid identifier name written directly in the code.

[True / False] Inside an object literal, using this.department.name to build a computed property key will correctly reference the object's own department property. A. True B. False

B. False — False. You cannot use this to refer to the object literal you are still in the middle of defining — the object doesn't exist yet while its own literal is being evaluated. this inside a method only works after the object exists and the method is called on it.

Create an object book with properties title, author, and a nested object details containing pages and published. Write a method summary() on book that returns a string combining the title, author, and page count using this.

const book = { title: "Clean Code", author: "Robert C. Martin", details: { pages: 464, published: 2008 }, summary() { return ${this.title} by ${this.author}, ${this.details.pages} pages; } }; console.log(book.summary()); // "Clean Code by Robert C. Martin, 464 pages"

Use this.title, this.author, and this.details.pages inside the method.