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.

JavaScriptbeginner
15 min read

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:

javascriptjavascript
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

javascriptjavascript
const emptyObj = {};
console.log(emptyObj); // {}
console.log(typeof emptyObj); // "object"

Object Constructor (Less Common)

javascriptjavascript
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:

javascriptjavascript
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

javascriptjavascript
const car = {
  brand: "Toyota",
  model: "Camry",
  year: 2024,
  color: "blue"
};
 
console.log(car.brand); // "Toyota"
console.log(car.year);  // 2024

Bracket 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:

javascriptjavascript
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); // SyntaxError

For a deeper comparison, see dot notation vs bracket notation.

FeatureDot NotationBracket Notation
Syntaxobj.keyobj["key"]
Dynamic keysNoYes (variables work)
Special characters in keysNoYes (spaces, hyphens)
ReadabilityMore readableLess readable
Use whenKey is a valid identifierKey is dynamic or contains special chars

Modifying Properties

Adding Properties

javascriptjavascript
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

javascriptjavascript
const settings = {
  theme: "light",
  fontSize: 14,
  language: "en"
};
 
settings.theme = "dark";
settings.fontSize = 16;
 
console.log(settings.theme);    // "dark"
console.log(settings.fontSize); // 16

Deleting Properties

javascriptjavascript
const profile = {
  name: "Bob",
  age: 30,
  tempToken: "abc123"
};
 
delete profile.tempToken;
 
console.log(profile);        // { name: "Bob", age: 30 }
console.log(profile.tempToken); // undefined

For more detail, see adding and deleting properties.

Checking if a Property Exists

javascriptjavascript
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
MethodChecks InheritedReturns
key in objYesBoolean
obj.hasOwnProperty(key)No (own properties only)Boolean
obj[key] !== undefinedOwn onlyBoolean (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.

javascriptjavascript
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); // 25

For 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:

javascriptjavascript
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:

javascriptjavascript
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); // 1

For a deep dive, see the this keyword in JavaScript objects.

Iterating Over Objects

for...in Loop

javascriptjavascript
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: 79

Object.keys(), Object.values(), Object.entries()

javascriptjavascript
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:

javascriptjavascript
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); // 200

Destructuring in Function Parameters

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
// 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

javascriptjavascript
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

javascriptjavascript
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()); // 42

Best Practices

  1. Use object literals ({}) over new Object() for clarity and brevity.
  2. Prefer dot notation for known property names; use bracket notation for dynamic access.
  3. Use destructuring for extracting multiple properties, especially in function parameters.
  4. Avoid arrow functions for methods when you need access to this.
  5. Use spread for immutable updates. { ...obj, updated: true } creates a new object without mutating the original.
  6. Check for null/undefined with optional chaining (?.) before accessing nested properties.
Rune AI

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 this to access sibling properties within the same object.
  • Destructuring simplifies property extraction: const { name, age } = user replaces multiple lines of manual assignment.
  • Objects are passed by reference: use spread ({ ...obj }) for shallow copies and structuredClone() for full deep copies.
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between an object and an array in JavaScript?

Objects store data as named key-value pairs accessed by string keys (like `user.name`). Arrays store ordered values accessed by numeric indices (like `items[0]`). Use objects when each piece of data has a meaningful name. Use arrays when order matters and the data is a collection of similar items. In practice, most applications use arrays of objects to represent collections of structured data.

Are JavaScript objects passed by reference or by value?

Objects are passed by reference. When you assign an object to a new variable or pass it to a function, both variables point to the same object in memory. Modifying the object through one variable changes it for all references. To create an independent copy, use the spread operator (`{ ...obj }`) for shallow copies or `structuredClone(obj)` for deep copies.

How do I check if an object is empty?

Use `Object.keys(obj).length === 0`. This returns `true` if the object has no own enumerable properties. You can wrap this in a utility function: `const isEmpty = (obj) => Object.keys(obj).length === 0`. Note that `{} === {}` returns `false` because it compares references, not contents.

What is the difference between Object.keys and for...in?

`Object.keys(obj)` returns an array of the object's own enumerable property names. `for...in` iterates over all enumerable properties, including inherited ones from the prototype chain. For most cases, `Object.keys` is safer because it only includes properties defined directly on the object. If you use `for...in`, add a `hasOwnProperty` check to exclude inherited properties.

When should I use Object.freeze()?

Use `Object.freeze(obj)` when you want to prevent any modifications to an object (no adding, removing, or changing properties). It is useful for constants, configuration objects, and ensuring immutability. Note that `Object.freeze` is shallow: nested objects inside a frozen object can still be modified. For deep immutability, you would need to recursively freeze all nested objects.

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.