What is an Object in JavaScript? Beginner Guide
Understand JavaScript objects from the ground up. Covers creating objects, accessing properties, adding and removing properties, methods, this keyword, object iteration, destructuring, and common patterns with real-world code examples.
An object in JavaScript is a collection of related data and functionality stored as key-value pairs. Unlike arrays, which store ordered lists accessed by numeric index, objects store named properties accessed by string keys. Objects model real-world entities: a user has a name, email, and age; a product has a title, price, and category. Almost everything in JavaScript is built on objects, making them the most important data type to understand.
This guide teaches you everything you need to know about JavaScript objects, from basic creation to methods, iteration, and destructuring.
Creating Objects
Object Literal (Most Common)
The object literal syntax uses curly braces with comma-separated key-value pairs:
const user = {
name: "Alice",
age: 28,
email: "alice@example.com",
isActive: true
};
console.log(user);
// { name: "Alice", age: 28, email: "alice@example.com", isActive: true }Empty Object
const emptyObj = {};
console.log(emptyObj); // {}
console.log(typeof emptyObj); // "object"Object Constructor (Less Common)
const product = new Object();
product.name = "Laptop";
product.price = 999;
product.inStock = true;The literal syntax ({}) is preferred because it is shorter and clearer.
Shorthand Property Names
When a variable name matches the property name, you can use shorthand:
const name = "Bob";
const age = 32;
const role = "developer";
// Longhand
const userLong = { name: name, age: age, role: role };
// Shorthand (ES6)
const userShort = { name, age, role };
console.log(userShort); // { name: "Bob", age: 32, role: "developer" }Accessing Properties
JavaScript provides two ways to read property values.
Dot Notation
const car = {
brand: "Toyota",
model: "Camry",
year: 2024,
color: "blue"
};
console.log(car.brand); // "Toyota"
console.log(car.year); // 2024Bracket Notation
Bracket notation uses a string (or variable) inside square brackets. It is required when property names contain spaces, special characters, or are stored in variables:
const car = {
brand: "Toyota",
"model-name": "Camry",
year: 2024
};
// Dynamic key access
const key = "brand";
console.log(car[key]); // "Toyota"
// Special characters in keys (dot notation won't work)
console.log(car["model-name"]); // "Camry"
// console.log(car.model-name); // SyntaxErrorFor a deeper comparison, see dot notation vs bracket notation.
| Feature | Dot Notation | Bracket Notation |
|---|---|---|
| Syntax | obj.key | obj["key"] |
| Dynamic keys | No | Yes (variables work) |
| Special characters in keys | No | Yes (spaces, hyphens) |
| Readability | More readable | Less readable |
| Use when | Key is a valid identifier | Key is dynamic or contains special chars |
Modifying Properties
Adding Properties
const user = { name: "Alice" };
// Add new properties
user.age = 28;
user.email = "alice@example.com";
user["phone-number"] = "555-0123";
console.log(user);
// { name: "Alice", age: 28, email: "alice@example.com", "phone-number": "555-0123" }Updating Properties
const settings = {
theme: "light",
fontSize: 14,
language: "en"
};
settings.theme = "dark";
settings.fontSize = 16;
console.log(settings.theme); // "dark"
console.log(settings.fontSize); // 16Deleting Properties
const profile = {
name: "Bob",
age: 30,
tempToken: "abc123"
};
delete profile.tempToken;
console.log(profile); // { name: "Bob", age: 30 }
console.log(profile.tempToken); // undefinedFor more detail, see adding and deleting properties.
Checking if a Property Exists
const config = {
debug: false,
port: 3000,
host: "localhost"
};
// Method 1: 'in' operator
console.log("debug" in config); // true
console.log("version" in config); // false
// Method 2: hasOwnProperty (excludes inherited properties)
console.log(config.hasOwnProperty("port")); // true
// Method 3: undefined check (less reliable)
console.log(config.debug !== undefined); // true
// Warning: fails if value is actually undefined| Method | Checks Inherited | Returns |
|---|---|---|
key in obj | Yes | Boolean |
obj.hasOwnProperty(key) | No (own properties only) | Boolean |
obj[key] !== undefined | Own only | Boolean (fails if value is undefined) |
Object.hasOwn(obj, key) | No (ES2022) | Boolean |
Object Methods
A method is a function stored as an object property. Methods let objects have behavior, not just data.
const calculator = {
result: 0,
add(value) {
this.result += value;
return this;
},
subtract(value) {
this.result -= value;
return this;
},
multiply(value) {
this.result *= value;
return this;
},
reset() {
this.result = 0;
return this;
},
getResult() {
return this.result;
}
};
// Method chaining (each method returns 'this')
const answer = calculator.reset().add(10).multiply(3).subtract(5).getResult();
console.log(answer); // 25For a complete guide to object methods, see JavaScript object methods tutorial.
The this Keyword
Inside an object method, this refers to the object the method belongs to:
const user = {
name: "Alice",
age: 28,
greet() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old.`;
},
birthday() {
this.age++;
return `Happy birthday! Now ${this.age}.`;
}
};
console.log(user.greet()); // "Hi, I'm Alice and I'm 28 years old."
console.log(user.birthday()); // "Happy birthday! Now 29."this with Arrow Functions (Common Trap)
Arrow functions do not have their own this. They inherit this from the enclosing scope:
const timer = {
seconds: 0,
// Bug: arrow function inherits 'this' from module/global scope
startBroken: () => {
this.seconds++; // 'this' is NOT the timer object
},
// Fix: use regular method syntax
startCorrect() {
this.seconds++;
}
};
timer.startCorrect();
console.log(timer.seconds); // 1For a deep dive, see the this keyword in JavaScript objects.
Iterating Over Objects
for...in Loop
const scores = {
math: 95,
science: 88,
english: 92,
history: 79
};
for (const subject in scores) {
console.log(`${subject}: ${scores[subject]}`);
}
// math: 95
// science: 88
// english: 92
// history: 79Object.keys(), Object.values(), Object.entries()
const inventory = {
apples: 12,
bananas: 24,
oranges: 8
};
// Keys only
console.log(Object.keys(inventory));
// ["apples", "bananas", "oranges"]
// Values only
console.log(Object.values(inventory));
// [12, 24, 8]
// Key-value pairs as arrays
console.log(Object.entries(inventory));
// [["apples", 12], ["bananas", 24], ["oranges", 8]]
// Practical: find the item with highest stock
const [topItem, topCount] = Object.entries(inventory)
.sort(([, a], [, b]) => b - a)[0];
console.log(`${topItem}: ${topCount}`); // "bananas: 24"Object Destructuring
Destructuring extracts properties into variables with concise syntax:
const user = {
name: "Alice",
age: 28,
role: "developer",
company: "TechCorp"
};
// Extract specific properties
const { name, role } = user;
console.log(name); // "Alice"
console.log(role); // "developer"
// Rename variables
const { name: userName, role: userRole } = user;
console.log(userName); // "Alice"
// Default values
const { name: n, country = "Unknown" } = user;
console.log(country); // "Unknown"
// Nested destructuring
const response = {
data: {
user: { id: 1, name: "Alice" },
token: "abc123"
},
status: 200
};
const { data: { user: { id }, token }, status } = response;
console.log(id); // 1
console.log(token); // "abc123"
console.log(status); // 200Destructuring in Function Parameters
function displayUser({ name, age, role = "viewer" }) {
console.log(`${name}, ${age}, ${role}`);
}
displayUser({ name: "Bob", age: 30, role: "admin" });
// "Bob, 30, admin"
displayUser({ name: "Charlie", age: 22 });
// "Charlie, 22, viewer"Copying and Merging Objects
Spread Operator
const defaults = {
theme: "light",
fontSize: 14,
sidebar: true
};
const userPrefs = {
theme: "dark",
fontSize: 18
};
// Merge: later properties overwrite earlier ones
const config = { ...defaults, ...userPrefs };
console.log(config);
// { theme: "dark", fontSize: 18, sidebar: true }Object.assign
const target = { a: 1, b: 2 };
const source = { b: 3, c: 4 };
const merged = Object.assign({}, target, source);
console.log(merged); // { a: 1, b: 3, c: 4 }Both methods create shallow copies. Nested objects are shared by reference. Use structuredClone() for deep copies.
Common Mistakes
Comparing Objects by Value
// Bug: objects are compared by reference, not by value
const a = { name: "Alice" };
const b = { name: "Alice" };
console.log(a === b); // false (different references)
// Fix: compare specific properties or use JSON
console.log(a.name === b.name); // true
console.log(JSON.stringify(a) === JSON.stringify(b)); // true (shallow)Accessing Properties on null/undefined
const user = null;
// Bug: TypeError: Cannot read properties of null
// console.log(user.name);
// Fix: optional chaining
console.log(user?.name); // undefined (no error)Using Arrow Functions as Methods
const obj = {
value: 42,
// Bug: arrow function has no own 'this'
getValue: () => this.value,
// Fix: use regular method
getValueFixed() {
return this.value;
}
};
console.log(obj.getValueFixed()); // 42Best Practices
- Use object literals (
{}) overnew Object()for clarity and brevity. - Prefer dot notation for known property names; use bracket notation for dynamic access.
- Use destructuring for extracting multiple properties, especially in function parameters.
- Avoid arrow functions for methods when you need access to
this. - Use spread for immutable updates.
{ ...obj, updated: true }creates a new object without mutating the original. - Check for null/undefined with optional chaining (
?.) before accessing nested properties.
Rune AI
Key Insights
- Objects store named key-value pairs: use them for structured data where each piece has a meaningful name.
- Dot notation is default, bracket notation handles dynamic keys: use brackets for variables, computed keys, and special characters.
- Methods give objects behavior: define functions as properties and use
thisto access sibling properties within the same object. - Destructuring simplifies property extraction:
const { name, age } = userreplaces multiple lines of manual assignment. - Objects are passed by reference: use spread (
{ ...obj }) for shallow copies andstructuredClone()for full deep copies.
Frequently Asked Questions
What is the difference between an object and an array in JavaScript?
Are JavaScript objects passed by reference or by value?
How do I check if an object is empty?
What is the difference between Object.keys and for...in?
When should I use Object.freeze()?
Conclusion
Objects are the backbone of JavaScript data modeling. They store named properties and methods, making them ideal for representing real-world entities like users, products, and configurations. Combined with arrays, they form the data structures behind every API response, database record, and user interface. Master property access (dot and bracket notation), modification (add, update, delete), iteration (Object.keys, values, entries), and destructuring, and you will have the tools to handle any JavaScript data structure confidently.
More in this topic
OffscreenCanvas API in JS for UI Performance
Master the OffscreenCanvas API to offload rendering from the main thread. Covers worker-based 2D and WebGL rendering, animation loops inside workers, bitmap transfer, double buffering, chart rendering pipelines, image processing, and performance measurement strategies.
Advanced Web Workers for High Performance JS
Master Web Workers for truly parallel JavaScript execution. Covers dedicated and shared workers, structured cloning, transferable objects, SharedArrayBuffer with Atomics, worker pools, task scheduling, Comlink RPC patterns, module workers, and performance profiling strategies.
JavaScript Macros and Abstract Code Generation
Master JavaScript code generation techniques for compile-time and runtime metaprogramming. Covers AST manipulation, Babel plugin authorship, tagged template literals as macros, code generation pipelines, source-to-source transformation, compile-time evaluation, and safe eval alternatives.