Skip to main content

Command Palette

Search for a command to run...

Understanding Objects in JavaScript

Updated
โ€ข14 min readโ€ขView as Markdown

1. What Are Objects and Why Do You Even Need Them?

Let's say you want to store information about a person.

With normal variables, you'd do this:

const name = "Priya";
const age = 22;
const city = "Delhi";

Okay. Works fine. But now add a second person:

const name2 = "Rahul";
const age2 = 25;
const city2 = "Mumbai";

Now a third person. A fourth. You now have 20 variables with zero connection to each other. You don't know which age belongs to which name. Your code is a mess.

Objects fix this completely.

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

Everything about Priya โ€” in one place. One variable. Clean, grouped, readable.

This is the whole point of objects: keep related data together.

Array vs Object โ€” Stop Confusing These Two

Both store multiple values. But they're for completely different jobs.

Array โ€” a list of similar items where position matters:

const scores = [95, 87, 70, 92];       // list of scores
const names  = ["Priya", "Rahul", "Sara"]; // list of names

You access them by position number: scores[0], names[2].

Object โ€” a collection of different details describing ONE thing:

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

You access them by label: person.name, person.age.

The simple test: "Is this a list of things?" โ†’ Array. "Is this details about one thing?" โ†’ Object.

A shopping cart is an array (list of items). A single product in that cart is an object (name, price, quantity, category).


๐Ÿ”ฅ Gotcha #1 โ€” typeof [] says "object" and it will confuse you

Run this in your console right now:

console.log(typeof [1, 2, 3]);  // "object"  โ† wait, that's an array!
console.log(typeof {});         // "object"

JavaScript says both are "object". This is a famous design mistake from 1995 that they can never fix because too much code depends on it.

So if you ever need to check whether something is an array, never use typeof:

// WRONG way
typeof [1, 2, 3] === "object"  // true, but so is {}... useless

// RIGHT way
Array.isArray([1, 2, 3])  // true  โœ…
Array.isArray({})          // false โœ…

Use Array.isArray(). Every time. No exceptions.

2. Creating Objects

The Main Way โ€” Object Literal Syntax

Curly braces, key-value pairs, commas between them:

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

The structure is always key: value. Keys on the left, colon in the middle, value on the right. Pairs separated by commas.

Values can be anything:

const person = {
  name: "Priya",            // string
  age: 22,                  // number
  isStudent: true,          // boolean
  hobbies: ["coding", "music"],   // array
  address: {                      // another object inside!
    city: "Delhi",
    pincode: "110001"
  }
};

Yes. Objects inside objects. Arrays inside objects. This is normal. This is how real data looks.

An Empty Object โ€” Totally Valid

const person = {};   // empty object, add stuff later

๐Ÿ”ฅ Gotcha #2 โ€” Keys with spaces or special characters must be quoted

const user = {
  name: "Priya",          // โœ… no quotes needed
  "full name": "Priya S", // โœ… must quote โ€” has a space
  "2fast": "yes",         // โœ… must quote โ€” starts with a number
  my-city: "Delhi"        // โŒ syntax error โ€” hyphen breaks it
};

JavaScript is fine with simple word keys without quotes. The moment your key has a space, hyphen, starts with a number, or has any special character โ€” wrap it in quotes. Otherwise you get a syntax error.

๐Ÿ”ฅ Gotcha #3 โ€” Two objects that look identical are NOT equal

const a = { name: "Priya" };
const b = { name: "Priya" };

console.log(a === b);  // false ๐Ÿ˜ฑ

This shocks everyone. They look the same. Same key, same value. But JavaScript says they're different.

Why? Because JavaScript doesn't compare what's inside the objects. It compares where they live in memory. a and b are two separate objects stored in two different memory locations. Different locations = not equal.

javascript

const a = { name: "Priya" };
const b = a;   // b now points to THE SAME object as a

console.log(a === b);  // true โœ…

Now they're equal because they point to the exact same memory location.

This also means: if you change b, you change a too โ€” because they're the same object:

b.name = "Rahul";
console.log(a.name);  // "Rahul" โ€” a changed too!

This is called reference behaviour and it bites every JavaScript developer at some point.

3. Accessing Properties

Dot Notation โ€” Simple and Clean

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

console.log(person.name);   // "Priya"
console.log(person.age);    // 22
console.log(person.city);   // "Delhi"

Object name, dot, key name. That's it. This is what you'll use 80% of the time.

Bracket Notation โ€” The Powerful One

console.log(person["name"]);  // "Priya"
console.log(person["age"]);   // 22

Same result, different syntax. Looks more verbose but has a superpower dot notation doesn't have: you can use a variable as the key.

const key = "name";

console.log(person[key]);   // "Priya" โ€” uses the variable's value
console.log(person.key);    // undefined โ€” literally looks for a key called "key"

When you write person.key, JavaScript looks for a key named key inside the object. There is none. Returns undefined.

When you write person[key], JavaScript evaluates the variable key, gets the value "name", then looks for a key named "name". Finds it. Returns "Priya".

This becomes incredibly useful when you're building dynamic code โ€” like reading a property based on user input or looping through keys programmatically.

๐Ÿ”ฅ Gotcha #4 โ€” Missing keys return undefined silently, no error

const person = { name: "Priya", age: 22 };

console.log(person.city);     // undefined โ€” not an error
console.log(person.country);  // undefined โ€” not an error

JavaScript just quietly returns undefined for any key that doesn't exist. No crash. No warning. Just undefined.

This is dangerous because your code keeps running with undefined as if it's a real value โ€” until it eventually breaks somewhere downstream and the error message points you to the wrong place.

๐Ÿ”ฅ Gotcha #5 โ€” Accessing a property of undefined will crash everything

The moment you go one level deeper on a missing key, JavaScript throws an error:

const person = { name: "Priya" };

console.log(person.address);         // undefined โ€” fine
console.log(person.address.city);    // โŒ TypeError: Cannot read properties of undefined

person.address is undefined. Then you try .city on undefined. That's the crash.

The modern fix is optional chaining ?.:

console.log(person.address?.city);   // undefined โ€” no crash โœ…
console.log(person.address?.city?.pincode);  // undefined โ€” no crash โœ…

The ?. means: "if the thing on my left is null or undefined, stop here and return undefined โ€” don't crash." Chain as many as you need.

๐Ÿ”ฅ Gotcha #6 โ€” Dot notation fails on keys with spaces

const user = {
  "full name": "Priya Sharma"
};

console.log(user.full name);       // โŒ syntax error
console.log(user["full name"]);    // โœ… "Priya Sharma"

Any key that required quotes when you created it โ€” will require bracket notation when you access it. Dot notation simply cannot handle keys with spaces, hyphens, or special characters.

4. Updating Object Properties

Objects are mutable. You can change their values after creation.

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

person.age = 23;           // update using dot notation
person["city"] = "Mumbai"; // update using bracket notation

console.log(person);
// { name: "Priya", age: 23, city: "Mumbai" }

Just assign a new value to the key. The old value is gone.

๐Ÿ”ฅ Gotcha #7 โ€” const does NOT protect object contents

This surprises everyone:

const person = { name: "Priya", age: 22 };

person.age = 30;      // โœ… works perfectly fine
person.name = "Raj";  // โœ… works perfectly fine

console.log(person);  // { name: "Raj", age: 30 }

You used const but the object still changed. How?

const only prevents you from pointing the variable at something new. It does NOT lock the contents:

person = { name: "Someone else" };  // โŒ TypeError โ€” can't reassign the variable

The variable person must always point to the same object. But that object's contents can be changed freely.

If you actually want to lock an object so nothing can change it, use Object.freeze():

const person = Object.freeze({ name: "Priya", age: 22 });

person.age = 30;          // silently ignored
console.log(person.age);  // still 22

One trap with freeze: it only freezes the top level. Nested objects inside are still mutable:

const person = Object.freeze({
  name: "Priya",
  address: { city: "Delhi" }  // this part is NOT frozen
});

person.address.city = "Mumbai";  // โœ… this works โ€” nested object is not frozen
console.log(person.address.city);  // "Mumbai"

There's no built-in deep freeze in JavaScript. You'd have to freeze each nested object manually.

5. Adding and Deleting Properties

Adding New Properties

You can add new properties any time โ€” even after the object was created:

javascript

const person = {
  name: "Priya",
  age: 22
};

person.city = "Delhi";        // add with dot notation
person["isStudent"] = true;   // add with bracket notation

console.log(person);
// { name: "Priya", age: 22, city: "Delhi", isStudent: true }

JavaScript objects are open by default โ€” new keys can be added at any point.

Deleting Properties

Use the delete keyword:

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

delete person.city;

console.log(person);       // { name: "Priya", age: 22 }
console.log(person.city);  // undefined

The key and value are completely removed.

๐Ÿ”ฅ Gotcha #8 โ€” delete is slow and often the wrong tool

JavaScript engines internally optimise objects by making assumptions about their shape (which keys they have). When you delete a property, the engine sometimes has to completely rebuild the object's internal structure. In tight loops over thousands of objects, this makes a real performance difference.

For most apps and UI code, delete is completely fine. But when performance matters, set the value to null instead:

person.city = null;       // key stays, value is null
person.city = undefined;  // key stays, value is undefined

The key still exists but the value signals "nothing here." Faster than deletion for the engine.

๐Ÿ”ฅ Gotcha #9 โ€” delete always returns true even when nothing was deleted

const person = { name: "Priya" };

console.log(delete person.name);    // true โ€” deleted it
console.log(delete person.xyz);     // true โ€” key didn't even exist, still says true

You'd think delete would return false when there's nothing to delete. Nope. It returns true unless the property is explicitly marked as non-deletable. For normal objects you create yourself, delete always returns true โ€” whether it did anything or not. Don't rely on the return value to check if a key existed.

6. Looping Through Object Keys

Arrays have indexes โ€” you can loop with for (let i = 0; i < arr.length; i++). Objects have no indexes. You need different tools.

Tool 1 โ€” for...in Loop

const person = {
  name: "Priya",
  age: 22,
  city: "Delhi"
};

for (let key in person) {
  console.log(key + ": " + person[key]);
}

// Output:
// name: Priya
// age: 22
// city: Delhi

for...in gives you one key at a time as a string. You use that key with bracket notation to get the value. Simple, readable.

Tool 2 โ€” Object.keys() โ€” Get All Keys as an Array

const keys = Object.keys(person);
console.log(keys);  // ["name", "age", "city"]

Now you have an array of keys. Use any array method you want on it:

Object.keys(person).forEach(key => {
  console.log(key + ": " + person[key]);
});

Tool 3 โ€” Object.values() โ€” Get All Values as an Array

const values = Object.values(person);
console.log(values);  // ["Priya", 22, "Delhi"]

Tool 4 โ€” Object.entries() โ€” Get Both Keys and Values Together

const entries = Object.entries(person);
console.log(entries);
// [["name", "Priya"], ["age", 22], ["city", "Delhi"]]

Object.entries(person).forEach(([key, value]) => {
  console.log(key + ": " + value);
});

Each item is a [key, value] pair. You destructure both directly in the loop. This is the most complete tool โ€” use it when you need both the key and value at the same time.

๐Ÿ”ฅ Gotcha #10 โ€” for...in picks up inherited properties

Here's a trap most tutorials never mention:

const person = { name: "Priya", age: 22 };

for (let key in person) {
  console.log(key);
}
// name
// age

Looks fine. But suppose some old third-party library you imported added something to Object.prototype:

Object.prototype.evil = "I snuck in";

for (let key in person) {
  console.log(key);
}
// name
// age
// evil  โ† this wasn't in your object!

for...in loops over ALL enumerable properties including inherited ones. The property evil wasn't in your object but it shows up anyway.

The safe fix:

for (let key in person) {
  if (person.hasOwnProperty(key)) {
    console.log(key);  // only logs keys that belong to THIS object
  }
}

Or just skip for...in entirely and use Object.keys() โ€” which automatically ignores inherited properties:

Object.keys(person).forEach(key => console.log(key));
// name
// age
// evil is gone โœ…

๐Ÿ”ฅ Gotcha #11 โ€” Integer keys get sorted to the front automatically

const obj = {
  city: "Delhi",
  3: "three",
  name: "Priya",
  1: "one",
  2: "two"
};

console.log(Object.keys(obj));
// ["1", "2", "3", "city", "name"]

You inserted city first. But JavaScript moved all the numeric keys to the front and sorted them numerically. Then the string keys follow in insertion order.

This matters when you have objects that mix number and string keys โ€” the output order will not match the order you wrote them. If you need guaranteed order, use a Map instead of an object.

Assignments โ€” Do These Before Moving On

Assignment 1 โ€” Build a Student Object

const student = {
  name: "Anjali",
  age: 20,
  course: "Computer Science",
  year: 2,
  isEnrolled: true
};

Assignment 2 โ€” Update a Property

student.age = 21;           // birthday happened
student.year = 3;           // moved to next year

Assignment 3 โ€” Loop and Print Everything

for (let key in student) {
  console.log(key + ": " + student[key]);
}

// name: Anjali
// age: 21
// course: Computer Science
// year: 3
// isEnrolled: true

Assignment 4 โ€” Add and Delete Properties

student.grade = "A";        // add new property
delete student.isEnrolled;  // remove old one

console.log(student);
// { name: "Anjali", age: 21, course: "Computer Science", year: 3, grade: "A" }

Assignment 5 โ€” Use Object.entries() to Print a Summary

Object.entries(student).forEach(([key, value]) => {
  console.log(`\({key} โ†’ \){value}`);
});

// name โ†’ Anjali
// age โ†’ 21
// course โ†’ Computer Science
// year โ†’ 3
// grade โ†’ A

The 11 Gotchas Recap

Keep this list:

  1. typeof [] returns "object" โ€” use Array.isArray() instead

  2. Keys with spaces or special characters must be in quotes

  3. Two objects with identical content are NOT equal โ€” objects compare by reference, not value

  4. Accessing a missing key returns undefined silently โ€” no error

  5. Accessing a property of undefined will crash โ€” use optional chaining ?.

  6. Dot notation fails on keys that have spaces โ€” use bracket notation

  7. const does NOT protect object contents โ€” only prevents variable reassignment

  8. delete is slow in performance-critical code โ€” set to null instead

  9. delete returns true even when the key didn't exist โ€” don't trust the return value

  10. for...in loops over inherited properties too โ€” use hasOwnProperty or Object.keys()

  11. Integer keys get sorted to the front automatically โ€” mixing number and string keys breaks expected order

More from this blog

blog about web dev

52 posts