JavaScriptBeginner

JavaScript Objects: Properties, Methods and Nested Data

Learn to create JavaScript objects, read and change properties, add methods, work with nested objects, and choose between dot and bracket notation.

All JavaScript lessons

What you will learn

An array is a list. But real things are not just lists. A student has a name, an age, a city and a course. A product has a title, a price and a stock count. To keep such related information together, JavaScript gives us objects. In this lesson you will learn how to create objects, read and change their properties, add methods (functions inside objects), work with nested objects, and understand when to use dot notation and when to use bracket notation.

What is an object?

Think of a student ID card. It has labels and values:

Label Value
Name Riya
Age 20
City Delhi

An object is exactly that: a collection of key-value pairs. The key is the label (also called the property name). The value is the information.

const student = {
  name: "Riya",
  age: 20,
  city: "Delhi"
};

console.log(student);   // { name: "Riya", age: 20, city: "Delhi" }

The rules are simple:

  • An object is written inside curly braces { }.
  • Each pair is written as key: value.
  • Pairs are separated by commas.
  • This way of creating an object is called an object literal.

A value can be anything: a string, a number, a boolean, an array, another object, or even a function.

const product = {
  title: "Wireless Mouse",
  price: 799,
  inStock: true,
  colors: ["black", "white"],
  rating: { score: 4.5, votes: 320 }
};

An empty object is just {}:

const emptyBox = {};
console.log(emptyBox);   // {}

Reading properties: dot notation

The most common way to read a value is dot notation: write the object, a dot, and the key.

const student = { name: "Riya", age: 20 };

console.log(student.name);   // "Riya"
console.log(student.age);    // 20

If the property does not exist, you do not get an error. You get undefined:

console.log(student.city);   // undefined

Reading properties: bracket notation

The second way is bracket notation: write the key as a string inside square brackets.

console.log(student["name"]);   // "Riya"
console.log(student["age"]);    // 20

Both ways give the same result. So why do we need two? Because bracket notation can do things that dot notation cannot.

1. When the key is stored in a variable

const prices = { apple: 120, banana: 40, mango: 90 };

const fruit = "banana";

console.log(prices[fruit]);    // 40  (uses the value of the variable)
console.log(prices.fruit);     // undefined  (looks for a key literally named "fruit")

This is the most important use. It lets one piece of code work for any key:

function getPrice(fruitName) {
  return prices[fruitName];
}

console.log(getPrice("mango"));    // 90
console.log(getPrice("apple"));    // 120

2. When the key has spaces, dashes or special characters

const settings = {
  "font-size": 16,
  "dark mode": true,
  1: "first"
};

console.log(settings["font-size"]);   // 16
console.log(settings["dark mode"]);   // true
console.log(settings[1]);             // "first"

settings.font-size would be read as settings.font minus size, which is wrong. Keys like these must be in quotes when you create them, and in brackets when you read them.

3. When the key is built from an expression

const user = { name_en: "Riya", name_hi: "रिया" };
const language = "hi";

console.log(user["name_" + language]);   // "रिया"

Dot or bracket: which one?

Dot notation Bracket notation
Example user.name user["name"]
Easier to read Yes A little less
Key must be a valid name Yes No, any text works
Key can come from a variable No Yes

Rule of thumb: use dot notation by default. Switch to bracket notation when the key is in a variable, or has spaces or special characters.

Adding, updating and deleting properties

Objects are changeable. You can add, update and remove properties at any time.

const user = { name: "Riya" };

// Add a new property
user.age = 20;
user["city"] = "Delhi";

// Update an existing property
user.name = "Riya Sharma";

// Delete a property
delete user.city;

console.log(user);   // { name: "Riya Sharma", age: 20 }

Assigning to a key that exists updates it. Assigning to a key that does not exist creates it.

const does not freeze the object

This surprises many beginners:

const user = { name: "Riya" };

user.name = "Karan";     // allowed
user.age = 25;           // allowed

console.log(user);       // { name: "Karan", age: 25 }
user = { name: "Amit" };   // TypeError: Assignment to constant variable.

const means you cannot point the variable to a different object. It does not stop you from changing what is inside the object. (If you want to lock the inside too, you will learn Object.freeze in the next lesson.)

Checking if a property exists

Reading a missing key gives undefined, but a key can also hold undefined on purpose. So the best way to check is one of these:

const user = { name: "Riya", age: 20, score: undefined };

console.log("age" in user);              // true
console.log("city" in user);             // false
console.log(Object.hasOwn(user, "age")); // true

// This check can be misleading:
console.log(user.score === undefined);   // true, but "score" does exist!
console.log("score" in user);            // true
  • "key" in object checks if the key exists (including inherited ones).
  • Object.hasOwn(object, "key") checks only the object’s own keys. This is usually what you want.

Shorthand and computed keys

When the variable name and the key are the same, you can write it once:

const name = "Riya";
const age = 20;

// Long way
const user1 = { name: name, age: age };

// Shorthand
const user2 = { name, age };

console.log(user2);   // { name: "Riya", age: 20 }

To build a key from a variable while creating the object, put it in square brackets. This is called a computed property name:

const field = "email";

const user = {
  name: "Riya",
  [field]: "riya@example.com"
};

console.log(user);   // { name: "Riya", email: "riya@example.com" }

Methods: functions inside objects

When a property’s value is a function, we call it a method. An object can not only store information, it can also do things with it.

const calculator = {
  add(a, b) {
    return a + b;
  },
  multiply(a, b) {
    return a * b;
  }
};

console.log(calculator.add(2, 3));        // 5
console.log(calculator.multiply(4, 5));   // 20

add(a, b) { ... } is the modern shorthand. The older way does the same thing:

const calculator = {
  add: function (a, b) {
    return a + b;
  }
};

Using other properties with this

A method often needs to use the object’s own data. Inside a method, the keyword this means the object that owns the method.

const student = {
  name: "Riya",
  marks: [80, 90, 70],

  average() {
    const total = this.marks.reduce((sum, m) => sum + m, 0);
    return total / this.marks.length;
  },

  introduce() {
    return `Hi, I am ${this.name}, and my average is ${this.average()}`;
  }
};

console.log(student.introduce());   // "Hi, I am Riya, and my average is 80"

Do not worry about the details of this yet. It has a full lesson of its own just after the next one. For now, remember: inside a method, this.something means “this object’s something”.

Tip: write methods with the shorthand name() { }, not with an arrow function. Arrow functions do not get this from the object (you saw why in the arrow functions lesson).

Nested objects

A property value can be another object. This is called a nested object. Real data is full of them.

const order = {
  id: 101,
  customer: {
    name: "Karan",
    address: {
      city: "Mumbai",
      pin: "400001"
    }
  },
  items: [
    { name: "Pen", qty: 2, price: 10 },
    { name: "Notebook", qty: 1, price: 60 }
  ]
};

To go deeper, just keep adding dots (or brackets):

console.log(order.customer.name);              // "Karan"
console.log(order.customer.address.city);      // "Mumbai"
console.log(order["customer"]["address"].pin); // "400001"  (you can mix both)

// Arrays inside objects: use an index
console.log(order.items[1].name);              // "Notebook"
console.log(order.items.length);               // 2

Updating a nested value works the same way:

order.customer.address.city = "Pune";
order.items.push({ name: "Eraser", qty: 3, price: 5 });

const total = order.items.reduce((sum, item) => sum + item.qty * item.price, 0);
console.log(total);   // 95   (2*10 + 1*60 + 3*5)

The nested trap: reading from undefined

If a middle part does not exist, JavaScript throws an error:

const user = { name: "Riya" };

try {
  console.log(user.address.city);
} catch (error) {
  console.log(error.name);      // "TypeError"
  console.log(error.message);   // Cannot read properties of undefined (reading 'city')
}

user.address is undefined, and you cannot read .city from undefined. A safe way is to check first:

if (user.address && user.address.city) {
  console.log(user.address.city);
} else {
  console.log("No address available");   // this runs
}

(There is a shorter and cleaner way, called optional chaining ?.. It has its own lesson soon.)

Objects are compared by reference

Two objects with the same content are not equal:

const a = { x: 1 };
const b = { x: 1 };
const c = a;

console.log(a === b);   // false  (two different objects)
console.log(a === c);   // true   (c points to the same object as a)

Also, when you copy a variable that holds an object, you do not get a new object:

const original = { name: "Riya" };
const same = original;

same.name = "Karan";
console.log(original.name);   // "Karan"  (it is the same object!)

The lesson on value vs reference explains this properly, and the next lessons show how to make real copies.

A few more facts

  • Keys are always text. { 1: "a" } stores the key as "1". Symbols are the only other kind of key (they have their own lesson later).
  • Order: when you list an object’s keys, whole-number keys come first in ascending order, then the other keys in the order you created them.
  • Duplicate keys: if you write the same key twice, the last one wins.
  • Objects are not iterable: you cannot use for...of on a plain object. Use for...in or the helpers from the next lesson.
const duplicate = { a: 1, b: 2, a: 3 };
console.log(duplicate);   // { a: 3, b: 2 }

const ordered = { b: "x", 2: "y", a: "z", 1: "w" };
console.log(Object.keys(ordered));   // ["1", "2", "b", "a"]

Real-life use cases

1. A user profile

const profile = {
  username: "riya_codes",
  email: "riya@example.com",
  isPremium: false,
  address: { city: "Delhi", country: "India" }
};

profile.isPremium = true;
profile.address.city = "Bengaluru";

console.log(`${profile.username} lives in ${profile.address.city}`);
// "riya_codes lives in Bengaluru"

2. A lookup table (replace long if/else chains)

const statusMessages = {
  200: "OK",
  404: "Page not found",
  500: "Server error"
};

function describeStatus(code) {
  return statusMessages[code] || "Unknown status";
}

console.log(describeStatus(404));   // "Page not found"
console.log(describeStatus(418));   // "Unknown status"

One object replaces a long if / else if / switch.

3. A shopping cart with methods

const cart = {
  items: [],

  addItem(name, price) {
    this.items.push({ name, price });
  },

  total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
};

cart.addItem("Pen", 10);
cart.addItem("Book", 250);

console.log(cart.items.length);   // 2
console.log(cart.total());        // 260

4. Collecting form values by field name

When a user types in a form, you often get the field name and the value. Bracket notation stores them neatly:

const formData = {};

function handleInput(fieldName, value) {
  formData[fieldName] = value;
}

handleInput("email", "riya@example.com");
handleInput("city", "Delhi");
handleInput("email", "riya.new@example.com");   // updates email

console.log(formData);   // { email: "riya.new@example.com", city: "Delhi" }

5. App settings with defaults

const settings = {
  theme: "dark",
  fontSize: 16,
  notifications: { email: true, sms: false }
};

settings.fontSize = 18;
settings.notifications.sms = true;

console.log(settings.notifications);   // { email: true, sms: true }

6. Reading API data

APIs usually send objects (as JSON). You read them with the same dots and brackets:

const apiResponse = {
  status: "success",
  data: {
    user: { id: 7, name: "Karan" },
    posts: [
      { id: 1, title: "Arrays" },
      { id: 2, title: "Objects" }
    ]
  }
};

console.log(apiResponse.data.user.name);        // "Karan"
console.log(apiResponse.data.posts[1].title);   // "Objects"
console.log(apiResponse.data.posts.length);     // 2

Common mistakes

  • Using dot notation with a variable. prices.fruit looks for a key named "fruit". Use prices[fruit].
  • Forgetting the quotes in brackets. user[name] uses the variable name. user["name"] uses the text "name".
  • Forgetting commas between properties. It causes a SyntaxError.
  • Using = instead of : when creating an object. Write { name: "Riya" }, not { name = "Riya" }.
  • Reading a property of undefined (user.address.city when there is no address). Check first, or use optional chaining later.
  • Thinking const makes an object unchangeable. It only stops re-assignment of the variable.
  • Comparing objects with === and expecting the content to be compared. Two separate objects are never equal.
  • Using an arrow function as a method and then using this. Use the method() { } shorthand.
  • Expecting a key to be a number. Keys are text, so Object.keys() gives "1", not 1.
  • Starting a statement with { and expecting an object. At the start of a line, JavaScript reads it as a block.

Practice

  1. Create an object book with title, author, price and inStock (a boolean). Print each property using dot notation.
  2. Print the same properties using bracket notation.
  3. Add a new property pages to book, change the price, and delete inStock. Print the object after every step.
  4. Create const key = "author"; and print book[key]. Then try book.key and explain why you get undefined.
  5. Create an object with the keys "first name" and "last-name". Print both values. Which notation must you use?
  6. Create a person object with a nested address object (city, pin). Change the city and print person.address.city.
  7. Add a method fullInfo() to person that returns a sentence using this.name and this.address.city.
  8. Build a menu object with the prices of 4 dishes. Write a function getPrice(dish) that returns the price, or "Not on the menu" if the dish is missing.
  9. Create an object with a scores array of 3 numbers and a method highest() that returns the largest score (use Math.max(...this.scores)).
  10. Challenge: create a bankAccount object with a balance and the methods deposit(amount), withdraw(amount) (do not allow a negative balance) and show().

Recap

  • An object stores related data as key-value pairs inside { }. Values can be anything, including arrays, objects and functions.
  • Read with dot notation (user.name) or bracket notation (user["name"]). Use brackets when the key is in a variable, or has spaces or special characters.
  • Assigning to a key adds it (if new) or updates it (if it exists). Use delete to remove one.
  • A missing property gives undefined, but reading from undefined throws a TypeError. Check with "key" in object or Object.hasOwn(object, "key").
  • A function stored in an object is a method. Inside it, this means the object itself.
  • Nested objects are read by chaining: order.customer.address.city.
  • const stops re-assignment, not changes inside the object. Objects are compared by reference, not by content.
  • Next you will learn the built-in Object methods: Object.keys, Object.values, Object.entries, Object.assign, Object.freeze and Object.seal.