Understanding Objects in JavaScript
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:
typeof []returns"object"โ useArray.isArray()insteadKeys with spaces or special characters must be in quotes
Two objects with identical content are NOT equal โ objects compare by reference, not value
Accessing a missing key returns
undefinedsilently โ no errorAccessing a property of
undefinedwill crash โ use optional chaining?.Dot notation fails on keys that have spaces โ use bracket notation
constdoes NOT protect object contents โ only prevents variable reassignmentdeleteis slow in performance-critical code โ set tonullinsteaddeletereturnstrueeven when the key didn't exist โ don't trust the return valuefor...inloops over inherited properties too โ usehasOwnPropertyorObject.keys()Integer keys get sorted to the front automatically โ mixing number and string keys breaks expected order