Objects and arrays are fundamental data structures in JavaScript that allow you to organize and manipulate complex data. Mastering these structures is essential for real-world applications.
Objects are collections of key-value pairs that allow you to store related data together. They are the foundation of JavaScript's object-oriented nature and provide a way to represent real-world entities in code.
Objects are dynamic collections where keys (also called properties) are strings or symbols, and values can be any data type, including other objects, functions, or primitive values.
The most common way to create objects is using object literal notation with curly braces:
const person = {
name: "John",
age: 30,
city: "New York"
};
You can also create objects using the Object constructor:
const car = new Object();
car.make = "Toyota";
car.model = "Camry";
car.year = 2020;
This method creates a new object with the specified prototype object:
const animal = {
type: "mammal",
sound: function() { return "makes sound"; }
};
const dog = Object.create(animal);
dog.breed = "Labrador";
You can access object properties using dot notation or bracket notation:
const book = {
title: "JavaScript Guide",
author: "Jane Doe",
pages: 250
};
// Dot notation
console.log(book.title);
// Bracket notation
console.log(book["author"]);
Bracket notation is particularly useful when property names contain special characters or are stored in variables:
const user = {
"first-name": "John",
"last name": "Doe"
};
const prop = "first-name";
console.log(user[prop]);
Objects are mutable, meaning you can add, modify, or delete properties:
const student = {};
student.name = "Alice";
student.grade = "A";
student.name = "Alice Smith"; // Modifying
delete student.grade; // Deleting
Every object property has descriptors that define its behavior:
const config = {};
Object.defineProperty(config, "version", {
value: "1.0",
writable: false,
enumerable: true,
configurable: false
});
JavaScript provides several built-in methods for working with objects:
const product = {
id: 1,
name: "Laptop",
price: 999
};
// Get all keys
console.log(Object.keys(product));
// Get all values
console.log(Object.values(product));
// Get all key-value pairs
console.log(Object.entries(product));
// Freeze object (prevent modifications)
Object.freeze(product);
// Seal object (prevent additions/deletions)
Object.seal(product);
This method copies all enumerable own properties from one or more source objects to a target object:
const target = { a: 1 };
const source = { b: 2, c: 3 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }
The this keyword refers to the object that is executing the current function. In object methods, this typically refers to the object itself:
const calculator = {
value: 0,
add: function(num) {
this.value += num;
return this.value;
},
reset: function() {
this.value = 0;
return this.value;
}
};
Arrays are ordered collections of values that can hold multiple items of different types in a single variable. Unlike objects, arrays maintain the order of elements and are indexed numerically starting from 0.
Arrays are dynamic and can grow or shrink in size, making them flexible for storing collections of data that need to be accessed by position.
The most common way to create arrays is using square brackets:
const fruits = ["apple", "banana", "orange"];
const numbers = [1, 2, 3, 4, 5];
const mixed = ["hello", 42, true, null];
You can also create arrays using the Array constructor:
const empty = new Array();
const withSize = new Array(5); // Creates array with 5 empty slots
const withElements = new Array("a", "b", "c");
These static methods provide additional ways to create arrays:
// Array.from() creates array from array-like objects
const str = "hello";
const chars = Array.from(str);
// Array.of() creates array from arguments
const nums = Array.of(1, 2, 3, 4, 5);
Array elements are accessed using zero-based indexing:
const colors = ["red", "green", "blue", "yellow"];
console.log(colors[0]); // "red"
console.log(colors[2]); // "blue"
console.log(colors[colors.length - 1]); // "yellow"
Arrays are mutable, so you can change elements by index:
const pets = ["cat", "dog", "fish"];
pets[1] = "hamster"; // Change "dog" to "hamster"
pets[3] = "bird"; // Add new element
The length property indicates the number of elements in an array:
const items = [10, 20, 30];
console.log(items.length); // 3
// You can also use length to truncate arrays
items.length = 2; // Now items is [10, 20]
These methods work at the end of the array:
const stack = [];
stack.push(1); // [1]
stack.push(2); // [1, 2]
const last = stack.pop(); // Returns 2, array is [1]
These methods work at the beginning of the array:
const queue = ["a", "b", "c"];
queue.unshift("x"); // ["x", "a", "b", "c"]
const first = queue.shift(); // Returns "x", array is ["a", "b", "c"]
This method can add, remove, or replace elements anywhere in the array:
const arr = [1, 2, 3, 4, 5];
arr.splice(2, 1, "x", "y"); // Remove 1 element at index 2, add "x", "y"
// Result: [1, 2, "x", "y", 4, 5]
Find the index of elements:
const data = [10, 20, 30, 20, 40];
console.log(data.indexOf(20)); // 1
console.log(data.lastIndexOf(20)); // 3
console.log(data.indexOf(50)); // -1 (not found)
Check if an element exists:
const tags = ["html", "css", "javascript"];
console.log(tags.includes("css")); // true
console.log(tags.includes("python")); // false
Find elements based on conditions:
const users = [
{ id: 1, name: "John", age: 25 },
{ id: 2, name: "Jane", age: 30 },
{ id: 3, name: "Bob", age: 35 }
];
const user = users.find(u => u.age > 28);
const index = users.findIndex(u => u.name === "Jane");
Create a new array with elements that pass a test:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = numbers.filter(n => n % 2 === 0);
// Result: [2, 4, 6, 8, 10]
Create a new array by transforming each element:
const nums = [1, 2, 3, 4];
const doubled = nums.map(n => n * 2);
// Result: [2, 4, 6, 8]
const users = [
{ first: "John", last: "Doe" },
{ first: "Jane", last: "Smith" }
];
const fullNames = users.map(u => `${u.first} ${u.last}`);
Reduce array to a single value:
const values = [1, 2, 3, 4, 5];
const sum = values.reduce((acc, val) => acc + val, 0);
// Result: 15
const words = ["hello", "world", "javascript"];
const sentence = words.reduce((acc, word) => acc + " " + word);
// Result: "hello world javascript"
Work with nested arrays:
const nested = [1, [2, 3], [4, [5, 6]]];
const flattened = nested.flat(2);
// Result: [1, 2, 3, 4, 5, 6]
const sentences = ["hello world", "javascript arrays"];
const words = sentences.flatMap(s => s.split(" "));
// Result: ["hello", "world", "javascript", "arrays"]
Sort array elements:
const fruits = ["banana", "apple", "orange"];
fruits.sort(); // ["apple", "banana", "orange"]
const numbers = [3, 1, 4, 1, 5, 9];
numbers.sort((a, b) => a - b); // [1, 1, 3, 4, 5, 9]
const people = [
{ name: "John", age: 25 },
{ name: "Jane", age: 30 }
];
people.sort((a, b) => a.age - b.age);
Reverse the order of elements:
const items = [1, 2, 3, 4, 5];
items.reverse(); // [5, 4, 3, 2, 1]
Destructuring allows you to extract properties from objects into distinct variables:
const person = {
name: "John",
age: 30,
city: "New York",
country: "USA"
};
// Basic destructuring
const { name, age } = person;
// With different variable names
const { name: fullName, age: years } = person;
// With default values
const { name, occupation = "Unknown" } = person;
// Nested destructuring
const user = {
profile: {
name: "Jane",
contact: {
email: "[email protected]",
phone: "123-456-7890"
}
}
};
const { profile: { name, contact: { email } } } = user;
Array destructuring allows you to extract elements from arrays:
const colors = ["red", "green", "blue", "yellow"];
// Basic destructuring
const [first, second] = colors;
// Skip elements
const [primary, , tertiary] = colors;
// Rest operator
const [head, ...tail] = colors;
// Default values
const [a, b, c, d, e = "purple"] = colors;
// Swapping variables
let x = 1, y = 2;
[x, y] = [y, x];
The spread operator expands iterables into individual elements:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
const original = [1, 2, 3];
const copy = [...original]; // Shallow copy
const withExtra = [...original, 4, 5]; // [1, 2, 3, 4, 5]
const person = { name: "John", age: 30 };
const employee = { ...person, id: 123, department: "IT" };
const original = { a: 1, b: 2 };
const updated = { ...original, b: 3, c: 4 }; // { a: 1, b: 3, c: 4 }
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 3
const parts = ["shoulders", "knees"];
const lyrics = ["head", ...parts, "and", "toes"];
The rest operator collects multiple elements into a single array:
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4, 5); // 15
function createUser(name, ...details) {
return { name, details };
}
createUser("John", 30, "Engineer", "NYC");
const [first, ...rest] = [1, 2, 3, 4, 5];
// first = 1, rest = [2, 3, 4, 5]
const { name, ...otherProps } = {
name: "John",
age: 30,
city: "NYC",
country: "USA"
};
// name = "John", otherProps = { age: 30, city: "NYC", country: "USA" }
Objects can contain other objects, creating complex data structures:
const company = {
name: "Tech Corp",
address: {
street: "123 Main St",
city: "San Francisco",
country: "USA"
},
employees: {
engineering: {
frontend: ["Alice", "Bob"],
backend: ["Charlie", "Diana"]
},
management: ["Eve", "Frank"]
}
};
// Accessing nested properties
const frontendTeam = company.employees.engineering.frontend;
const city = company.address.city;
Arrays can contain other arrays or objects:
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
const users = [
{ id: 1, name: "John", hobbies: ["reading", "coding"] },
{ id: 2, name: "Jane", hobbies: ["painting", "music"] }
];
// Accessing nested elements
const center = matrix[1][1]; // 5
const johnHobbies = users[0].hobbies; // ["reading", "coding"]
const nested = [1, [2, 3], [4, [5, 6]]];
const flattened = nested.flat(Infinity);
const deepFlatten = (arr) => {
return arr.reduce((flat, item) => {
return flat.concat(Array.isArray(item) ? deepFlatten(item) : item);
}, []);
};
When working with objects and arrays, prefer immutable operations:
// Instead of modifying original
const user = { name: "John", age: 30 };
user.age = 31; // Mutable
// Prefer creating new objects
const updatedUser = { ...user, age: 31 }; // Immutable
// Instead of modifying array
const items = [1, 2, 3];
items.push(4); // Mutable
// Prefer creating new arrays
const newItems = [...items, 4]; // Immutable
Use proper methods to check if something is an object or array:
const data = { a: 1 };
const list = [1, 2, 3];
console.log(typeof data); // "object"
console.log(Array.isArray(data)); // false
console.log(Array.isArray(list)); // true
// Better object check
const isObject = (obj) => {
return obj !== null && typeof obj === "object" && !Array.isArray(obj);
};
For deep cloning objects and arrays:
// Using JSON (limited - doesn't handle functions, undefined, etc.)
const deepClone = JSON.parse(JSON.stringify(original));
// Using structuredClone (modern browsers)
const deepClone = structuredClone(original);
// Manual deep clone function
function deepClone(obj) {
if (obj === null || typeof obj !== "object") return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof Array) return obj.map(item => deepClone(item));
const cloned = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
for loops are generally fastest for simple iterationsforEach() is readable but slightly slowermap(), filter(), reduce() create new arrays (memory overhead)for...of is good for iterating over values// Don't use arrays for key-value pairs
const bad = [];
bad["name"] = "John"; // Creates sparse array
bad.length; // 0, not 1
// Use objects instead
const good = {};
good.name = "John";
const arr1 = [1, 2, 3];
const arr2 = arr1; // Reference, not copy
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4] - arr1 is also changed!
// Use spread for copying
const arr3 = [...arr1];
// Don't use this for arrays
if (arr) { /* arr could be [0] which is truthy but not empty */ }
// Use length instead
if (arr.length === 0) { /* empty array */ }
// For objects
if (Object.keys(obj).length === 0) { /* empty object */ }
// Transform API response
const apiData = {
users: [
{ id: 1, first_name: "John", last_name: "Doe", age: 25 },
{ id: 2, first_name: "Jane", last_name: "Smith", age: 30 }
]
};
const transformed = apiData.users.map(user => ({
id: user.id,
fullName: `${user.first_name} ${user.last_name}`,
isAdult: user.age >= 18
}));
const products = [
{ category: "electronics", name: "Laptop", price: 999 },
{ category: "electronics", name: "Phone", price: 699 },
{ category: "books", name: "JavaScript Guide", price: 29 }
];
const grouped = products.reduce((acc, product) => {
const category = product.category;
if (!acc[category]) {
acc[category] = [];
}
acc[category].push(product);
return acc;
}, {});
const users = [
{ name: "John", skills: ["JavaScript", "React"], active: true },
{ name: "Jane", skills: ["Python", "Django"], active: false },
{ name: "Bob", skills: ["JavaScript", "Node.js"], active: true }
];
// Find active JavaScript developers
const jsDevs = users.filter(user =>
user.active && user.skills.includes("JavaScript")
);
// Get all unique skills
const allSkills = [...new Set(
users.flatMap(user => user.skills)
)];
Objects and arrays are fundamental building blocks in JavaScript that enable you to work with complex data structures effectively.
Mastering objects and arrays will significantly improve your ability to write clean, efficient, and maintainable JavaScript code.