JavaScript Objects

While Arrays are perfect for ordered lists (1st, 2nd, 3rd), they are terrible for describing a single entity with multiple characteristics.

If you have a user, you don’t want to remember that index 0 is their name and index 1 is their email. Instead, we use Objects.

An Object is a collection of related data stored in Key-Value Pairs. It models real-world things (like a car, a user, or a product) where data is accessed by a label (the Key) rather than a number.

Just like arrays, there is a standard way and a way to avoid.

The Object Literal (Standard)

The “literal” syntax uses curly braces {}. This is how 99% of objects are created.

// An empty object
const emptyObj = {};
console.log(emptyObj);
// Output: {}

// Object Literal Syntax
const user = {
	firstName: "Rodney",
	lastName: "Mullen",
	age: 57,
	isPro: true
};
console.log(user);
// Output: {firstName: 'Rodney', lastName: 'Mullen', age: 57, isPro: true}
JavaScript

Modern Syntax: Property Shorthand (ES6)

In modern engineering, if the variable name matches the key name, you can skip the colon and value. This is extremely common in React and Node.js.

// Shorthand Syntax (variable name as key name):
const userName = "Rodney";
const userRole = "Admin";
const user = { userName, userRole }; 
console.log(user); // Output: { userName: "Rodney", userRole: "Admin" }
JavaScript

The Object Constructor (AVOID)

You can use the new keyword, but it is verbose and rarely used in modern JavaScript for plain objects.

// Object Constructor (AVOID):
const user2 = new Object();
user2.name = "Tony";
console.log(user2); 
// Output: {name: 'Tony'}
JavaScript

Unlike arrays which use numbers, Objects use Keys (strings) to access data. There are two distinct notations.

Dot Notation . (Preferred)

The cleanest syntax. Use this when you know the name of the property you want.

// Accessing Properties with Dot Notation:
const car = {
	brand: "Tesla",
	model: "Model 3",
	color: "Red"
};
console.log(car.brand); // Output: Tesla
console.log(car.model); // Output: Model 3
// Accessing a key that doesn't exist returns 'undefined'
console.log(car.price); // Output: undefined
JavaScript

Bracket Notation [] (Dynamic)

Bracket notation is required when the key is stored in a variable or contains special characters (like spaces).

// Bracket Notation [] (required when key has special
// characters such as "-" dashes or spaces):
const item = {
	"product-id": 12345,
	productName: "T-Shirt",
	"product price": 19.99
};
console.log(item["product-id"]); // Output: 12345
console.log(item["product price"]); // Output: 19.99
// console.log(item.product-id); // ReferenceError
// console.log(item[productName]); // ReferenceError

// 2. Dynamic Keys (The Variable Trap)
const searchKey = "product price";
console.log(item[searchKey]); // Output: 19.99
console.log(item.searchKey); // Output: undefined (Looks for key named "searchKey")
JavaScript

Objects are Mutable. Even if declared with const, you can change, add, or delete properties inside them.

// Modifying Objects (objects are mutable, even with const):
const laptop = {
    brand: "Apple",
    chip: "M1"
};

// ADDING a new property
laptop.screenSize = 13;
console.log(laptop); // {brand: 'Apple', chip: 'M1', screenSize: 13}

// MODIFYING an existing property
laptop.chip = "M2";
console.log(laptop); // {brand: 'Apple', chip: 'M2', screenSize: 13}

// DELETING a property
delete laptop.brand;
console.log(laptop); // {chip: 'M2', screenSize: 13}
/* Note: the "delete" keyword can also be used to remove elements in arrays. */
JavaScript

Note: Just like arrays, const prevents you from reassigning the variable (laptop = {} will fail), but it allows you to edit the content inside.

Computed Property Names (ES6)

You can create a dynamic key inside the object definition using square brackets.

// Computed Property Names (ES6):
const keyName = "status";
const statusValue = "Active";
const userState = {
	id: 1,
	[keyName]: statusValue // Creates a key named "status"
};
console.log(userState); // { id: 1, status: "Active" }
JavaScript

Destructuring allows you to “unpack” properties from an object into distinct variables.

// Object Destructuring (assigning key/value to variable/value):
const movie = {
	title: "Inception",
	director: "Nolan",
	year: 2010
};

// The Old Way
// const title = movie.title;
// const director = movie.director;

// The Destructuring Way
// JS finds the property matching the variable name and unpacks it.
const { title, director } = movie;
console.log(title); // Output: Inception
console.log(director); // Output: Nolan

const {year} = movie;
console.log(year); // Output: 2010
JavaScript

Destructuring: Renaming Variables

Sometimes you want to unpack a property but call it something else in your code (e.g., to avoid naming collisions).

// Object Destructuring - Naming Variables:
const person = {
	userName: "Rodney",
	job: "Developer"
};
// Keeping variable name same as Object key:
const {userName} = person;
console.log(userName); // Output: Rodney
// Extract 'name' key but call the variable 'fullName':
const { userName: fullName } = person;
console.log(fullName); // Output: Rodney
JavaScript

Destructuring: Default Values

You can set a fallback value if the property you are trying to unpack is undefined (missing).

// Object Destructuring - Default Values:
const settings = { 
   theme: "Dark" 
   // fontSize is missing here
};
// We extract 'theme' (exists) and 'fontSize' (missing, so use fallback)
const { theme = "Light", fontSize = "16px" } = settings;
console.log(theme); // Output: "Dark" (Object value wins)
console.log(fontSize); // Output: "16px" (Default fallback wins)
JavaScript

Just like arrays, the Spread operator (...) is used to Clone and Merge objects.

// Spread Operator (...) - Clone and Merge Objects:
const basicUser = {
	name: "Rod",
	email: "[email protected]"
};

// Copying an Object (Shallow Copy):
const clone = { ...basicUser };
console.log(clone); // {name: "Rod", email: "[email protected]"}

// Merging Objects (Adding/Overwriting properties):
const fullProfile = { 
	...basicUser, 
	age: 30, // Adding new property
	name: "Rodney" // Overwriting existing property
};
console.log(fullProfile); 
// Output: {name: "Rodney", email: "[email protected]", age: 30}
JavaScript

Note: The order matters. If you place name: "Rodney" BEFORE the ...basicUser spread, the original name (“Rod”) from the spread would overwrite your new one.

Warning: Shallow Copies with (...) spread.

Using ...spread creates a Shallow Copy. This means it duplicates the top-level properties (like strings and numbers) perfectly, but it does not create copies of nested objects. Nested objects are passed by Reference, meaning the copy points to the same data in memory as the original.

// Shallow Copy Example:
const original = {
   name: "Rodney",
   details: {
      age: 30
   }
};
const shallowCopy = { ...original }; // Using spread syntax

shallowCopy.name = "Bob"; // Primitive change: original.name remains "Rodney" (Safe)
shallowCopy.details.age = 31; // Nested object change: original.details.age also becomes 31! (Shared Reference)

console.log(original.name); // "Rodney"
console.log(original.details.age); // 31 (The original was accidentally modified!)
JavaScript

To fix this in modern JavaScript, use structuredClone(original) to create a Deep Copy where nothing is shared.

Used during destructuring to collect “everything else” into a specific object. This is a common pattern for “removing” a property immutably (by extracting it and keeping the rest).

// Rest Operator (...) - include "everything" else into an object:
const data = { id: 1, title: "Post 1", views: 500, likes: 100 };

// Extract 'id' to a variable, put the REST in a variable called 'stats':
const { id, ...stats } = data;

console.log(id); // 1
console.log(stats); // { title: "Post 1", views: 500, likes: 100 }
JavaScript

Objects can hold other objects. This is standard for API responses (like JSON).

// Multi-Dimensional Objects (Nested):
const userProfile = {
	id: 101,
	details: {
		name: "Sarah",
		address: {
			city: "New York",
			zip: 10001
		}
	}
};
// Accessing Nested Data (Dot Chaining)
console.log(userProfile.details.address.city); // Output: New York
JavaScript

Optional Chaining ?. (Modern JS)

When accessing deeply nested data, your code will crash if an intermediate property is missing (e.g., if address doesn’t exist). The Optional Chaining operator (?.) solves this safely.

// Optional Chaining "?.":
const userNoAddress = {
	id: 102,
	details: {
		name: "John"
	}
};
// console.log(userNoAddress.details.address.city); 
// Without ?.: Code crashes with "Cannot read property 'city' of undefined"

// With ?.: Returns 'undefined' instead of crashing
console.log(userNoAddress.details?.address?.city); // Output: undefined
JavaScript

Since both can hold data, which should we use?

  • Use Arrays when you have a list of similar items (e.g., a list of messages) and order matters.
  • Use Objects when you have a single entity with named characteristics (e.g., a specific message with text, timestamp, and sender).

Technical Check:

Unlike Arrays, Objects have their own dedicated typeof result.

const obj = {};
console.log(typeof obj); // Output: "object"
JavaScript
ConceptSyntax ExampleDescription
Creationconst obj = {}Creating an empty object literal.
Shorthand{ name, age }Creating props from variables with same name.
Dot Accessobj.keyStandard access. Key must be a valid identifier.
Bracket Accessobj["key"]Dynamic access. Allows variables/spaces in keys.
Computed Prop{ [key]: val }Creating a dynamic key inside definition.
Destructuringconst { a, b } = objUnpacking properties into variables.
Renamingconst { a: x } = objUnpacking a but renaming the variable to x.
Spreadconst newObj = {…obj}Cloning or merging objects.
Restconst {a, …rest} = objCollecting remaining properties into a new object.
Optional Chainobj?.propSafely accessing nested data without crashing.
Deletedelete obj.keyRemoving a property from an object.

Why This Matters: Objects are the foundation of JavaScript. If you look closely, almost everything in JavaScript (including Arrays and Functions) is technically an object under the hood. Mastering key-value data modeling is essential for working with APIs, databases, and application state.