Chapter 8 Intermediate 28 min min read Updated 2026-04-09

Arrays and Array Methods

Practice Questions →

In This Chapter

What Is It?

What Are Arrays in JavaScript?

An array is an ordered collection of values stored in a single variable. Instead of creating separate variables for 100 student names, you store them all in one array and access any of them by position (index).

Arrays in JavaScript are flexible. They can hold any type of data: numbers, strings, booleans, objects, and even other arrays. They can also grow and shrink dynamically - you do not need to specify a size when creating one.

const fruits = ["apple", "mango", "banana"];
const scores = [85, 92, 78, 95, 88];
const mixed = ["Aarav", 16, true, null];

Each element has an index, starting at 0. The first element is at index 0, the second at index 1, and so on. You access elements using square brackets: fruits[0] gives "apple".

Why Does It Matter?

Why Are Arrays Important?

Arrays are one of the most used data structures in all of programming. Here is why you need to master them:

1. Real Data Comes in Lists

Student names, product prices, quiz scores, blog posts, search results - almost all real data is a collection of items. Arrays are how JavaScript stores and works with these collections.

2. Powerful Built-in Methods

JavaScript arrays come with dozens of built-in methods like map(), filter(), reduce(), sort(), and find(). These methods let you transform, filter, search, and process data in just one or two lines of code.

3. Building Dynamic UIs

Every time you see a list of products on Amazon, search results on Google, or posts on Instagram, an array of data was processed and turned into HTML elements. Arrays are the backbone of dynamic web pages.

4. API Data Processing

When you fetch data from an API (like weather data or movie listings), it almost always comes as an array of objects. You need array methods to filter, sort, and display this data.

5. Foundation for Advanced Patterns

Method chaining, functional programming, state management in React, and data pipelines all rely heavily on array methods. If you master arrays, everything else becomes easier.

Detailed Explanation

Detailed Explanation

1. Creating and Accessing Arrays

You create arrays using square brackets. Access elements by their index (starting at 0). Modify elements by assigning to an index.

const colors = ["red", "green", "blue"];
console.log(colors[0]);    // "red"
console.log(colors[2]);    // "blue"
console.log(colors.length); // 3

colors[1] = "yellow"; // Modify an element
console.log(colors);  // ["red", "yellow", "blue"]

Note: even though the array is declared with const, you can still modify its contents. The const only prevents reassigning the variable, not changing the array itself.

2. Adding and Removing Elements

JavaScript provides methods to add and remove elements from both ends of an array:

const arr = [1, 2, 3];

arr.push(4);     // Add to end: [1, 2, 3, 4]
arr.pop();       // Remove from end: [1, 2, 3]
arr.unshift(0);  // Add to start: [0, 1, 2, 3]
arr.shift();     // Remove from start: [1, 2, 3]

push and pop work on the end. unshift and shift work on the start. push and unshift return the new length. pop and shift return the removed element.

3. splice and slice

splice changes the array in place - it can remove, replace, or insert elements at any position:

const arr = ["a", "b", "c", "d", "e"];

arr.splice(2, 1);          // Remove 1 element at index 2: ["a", "b", "d", "e"]
arr.splice(1, 0, "x");     // Insert "x" at index 1: ["a", "x", "b", "d", "e"]
arr.splice(0, 2, "y", "z"); // Replace 2 elements at start: ["y", "z", "b", "d", "e"]

slice creates a new array from a portion of the original, without modifying it:

const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(1, 4)); // [2, 3, 4] (index 1 to 3)
console.log(arr.slice(2));    // [3, 4, 5] (index 2 to end)
console.log(arr);             // [1, 2, 3, 4, 5] (unchanged)

4. Searching: indexOf, includes, find, findIndex

const nums = [10, 20, 30, 40, 50];

nums.indexOf(30);     // 2 (index of first match)
nums.includes(20);    // true (does it exist?)
nums.find(n => n > 25);      // 30 (first element passing the test)
nums.findIndex(n => n > 25); // 2 (index of first element passing the test)

indexOf and includes work with simple values. find and findIndex take a callback function, making them powerful for complex conditions.

5. map - Transform Every Element

map() creates a new array by calling a function on every element of the original:

const prices = [100, 200, 300];
const withTax = prices.map(price => price * 1.18);
console.log(withTax); // [118, 236, 354]

The original array is unchanged. map always returns a new array of the same length. It is the most common array method in web development.

6. filter - Select Elements

filter() creates a new array with only the elements that pass a test:

const scores = [85, 42, 67, 91, 38, 73];
const passing = scores.filter(s => s >= 50);
console.log(passing); // [85, 67, 91, 73]

The callback must return true or false. Elements where the callback returns true are included; others are excluded.

7. reduce - Accumulate to a Single Value

reduce() processes all elements and reduces them to a single value (a number, string, object, etc.):

const nums = [1, 2, 3, 4, 5];
const sum = nums.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15

The callback takes an accumulator (running result) and the current element. The second argument to reduce (0) is the initial value of the accumulator. Step by step: 0+1=1, 1+2=3, 3+3=6, 6+4=10, 10+5=15.

8. sort - Ordering Elements

sort() sorts the array in place (modifies the original). By default, it sorts elements as strings, which causes problems with numbers:

const nums = [40, 100, 1, 5, 25];
nums.sort(); // [1, 100, 25, 40, 5] - WRONG! (string comparison)

// Correct: use a compare function
nums.sort((a, b) => a - b); // [1, 5, 25, 40, 100] - ascending
nums.sort((a, b) => b - a); // [100, 40, 25, 5, 1] - descending

The compare function returns a negative number (a comes first), zero (equal), or positive number (b comes first).

9. forEach - Do Something for Each Element

forEach() calls a function for each element but does NOT return a new array. Use it for side effects like logging or DOM manipulation:

const names = ["Aarav", "Priya", "Rohan"];
names.forEach((name, index) => {
  console.log(index + 1 + ". " + name);
});

10. every and some

every() checks if ALL elements pass a test. some() checks if AT LEAST ONE element passes:

const ages = [15, 17, 14, 16, 18];
ages.every(a => a >= 18); // false (not all are 18+)
ages.some(a => a >= 18);  // true (at least one is 18+)

11. Spread Operator [...] and Array.from()

The spread operator (...) expands an array into individual elements. It is great for copying and merging arrays:

const a = [1, 2, 3];
const b = [4, 5, 6];
const combined = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
const copy = [...a];           // [1, 2, 3] (shallow copy)

Array.from() creates an array from array-like objects:

Array.from("hello");     // ["h", "e", "l", "l", "o"]
Array.from({length: 5}, (_, i) => i * 2); // [0, 2, 4, 6, 8]

12. flat and flatMap

flat() flattens nested arrays. flatMap() maps and flattens in one step:

const nested = [[1, 2], [3, 4], [5, 6]];
nested.flat(); // [1, 2, 3, 4, 5, 6]

const sentences = ["hello world", "goodbye moon"];
sentences.flatMap(s => s.split(" ")); // ["hello", "world", "goodbye", "moon"]

13. Method Chaining

Since methods like map, filter, and sort return arrays, you can chain them together:

const students = [
  { name: "Aarav", score: 85 },
  { name: "Priya", score: 42 },
  { name: "Rohan", score: 91 },
  { name: "Diya", score: 67 }
];

const topScorers = students
  .filter(s => s.score >= 60)
  .sort((a, b) => b.score - a.score)
  .map(s => s.name);

console.log(topScorers); // ["Rohan", "Aarav", "Diya"]

This reads like a pipeline: filter out low scores, sort by score descending, then extract just the names. Chaining is extremely common in real JavaScript.

14. Destructuring Arrays

Destructuring lets you unpack array values into individual variables:

const [first, second, third] = ["apple", "mango", "banana"];
console.log(first);  // "apple"
console.log(second); // "mango"

// Skip elements
const [a, , c] = [1, 2, 3];
console.log(a, c); // 1 3

// Rest pattern
const [head, ...tail] = [10, 20, 30, 40];
console.log(head); // 10
console.log(tail); // [20, 30, 40]

Code Examples

Creating, Accessing, and Modifying Arrays
const students = ["Aarav", "Priya", "Rohan", "Diya", "Vikram"];

// Accessing elements
console.log(students[0]);       // First element
console.log(students[students.length - 1]); // Last element

// Modifying
students[2] = "Arjun";
console.log(students);

// Length
console.log("Count:", students.length);
Arrays are zero-indexed: the first element is at index 0. Access the last element using arr[arr.length - 1]. You can modify elements by assigning to an index, even with const (const prevents reassignment of the variable, not mutation of the array).
Aarav Vikram ["Aarav", "Priya", "Arjun", "Diya", "Vikram"] Count: 5
push, pop, shift, unshift, splice
const queue = ["Meera", "Kabir", "Ananya"];

queue.push("Ishaan");    // Add to end
console.log(queue);

const removed = queue.shift(); // Remove from start
console.log("Served:", removed);
console.log(queue);

// splice: insert at index 1
queue.splice(1, 0, "Neha");
console.log(queue);

// splice: remove 2 elements starting at index 0
queue.splice(0, 2);
console.log(queue);
push adds to the end, shift removes from the start (like a real queue). splice(index, deleteCount, ...items) is the Swiss army knife: it can insert, remove, or replace elements at any position.
["Meera", "Kabir", "Ananya", "Ishaan"] Served: Meera ["Kabir", "Ananya", "Ishaan"] ["Kabir", "Neha", "Ananya", "Ishaan"] ["Ananya", "Ishaan"]
map, filter, and reduce
const marks = [85, 42, 91, 67, 38, 73, 55];

// map: add 5 bonus marks to each
const boosted = marks.map(m => m + 5);
console.log("Boosted:", boosted);

// filter: only passing marks (>= 50)
const passing = marks.filter(m => m >= 50);
console.log("Passing:", passing);

// reduce: calculate average
const total = marks.reduce((sum, m) => sum + m, 0);
const average = total / marks.length;
console.log("Average:", average.toFixed(1));
map transforms every element (adds 5 to each mark). filter keeps only elements passing a condition (marks >= 50). reduce compresses the array into a single value (sum of all marks). None of these modify the original array.
Boosted: [90, 47, 96, 72, 43, 78, 60] Passing: [85, 91, 67, 73, 55] Average: 64.4
Method Chaining with Real Data
const products = [
  { name: "Laptop", price: 45000, inStock: true },
  { name: "Phone", price: 15000, inStock: false },
  { name: "Tablet", price: 25000, inStock: true },
  { name: "Watch", price: 8000, inStock: true },
  { name: "Headphones", price: 3000, inStock: true }
];

const affordable = products
  .filter(p => p.inStock)
  .filter(p => p.price <= 25000)
  .sort((a, b) => a.price - b.price)
  .map(p => p.name + " (Rs " + p.price + ")");

console.log("Affordable in-stock items:");
affordable.forEach(item => console.log("- " + item));
This chain first filters products that are in stock, then filters by price, sorts by price ascending, and finally maps to display strings. Each method returns a new array, so you can keep chaining. This is how real e-commerce sites process product data.
Affordable in-stock items: - Headphones (Rs 3000) - Watch (Rs 8000) - Tablet (Rs 25000)
sort with Compare Function
// Sorting numbers (must use compare function)
const nums = [40, 100, 1, 5, 25, 10];

// Default sort (wrong for numbers!):
const defaultSort = [...nums].sort();
console.log("Default:", defaultSort);

// Ascending
const ascending = [...nums].sort((a, b) => a - b);
console.log("Ascending:", ascending);

// Descending
const descending = [...nums].sort((a, b) => b - a);
console.log("Descending:", descending);

// Sort strings alphabetically
const names = ["Rohan", "Aarav", "Priya", "Diya"];
names.sort();
console.log("Names:", names);
Default sort() converts everything to strings, which gives wrong results for numbers (100 comes before 25 alphabetically). Always use a compare function for numbers: (a, b) => a - b for ascending, (a, b) => b - a for descending. We use [...nums] to copy the array before sorting since sort modifies in place.
Default: [1, 10, 100, 25, 40, 5] Ascending: [1, 5, 10, 25, 40, 100] Descending: [100, 40, 25, 10, 5, 1] Names: ["Aarav", "Diya", "Priya", "Rohan"]
Spread Operator, Array.from, and Destructuring
// Spread: merge arrays
const frontEnd = ["HTML", "CSS", "JavaScript"];
const backEnd = ["Node", "Python", "Java"];
const fullStack = [...frontEnd, ...backEnd];
console.log("Full stack:", fullStack);

// Array.from: create array from a range
const evens = Array.from({ length: 5 }, (_, i) => (i + 1) * 2);
console.log("Evens:", evens);

// Destructuring
const [gold, silver, bronze, ...rest] = ["Aarav", "Priya", "Rohan", "Diya", "Vikram"];
console.log("Gold:", gold);
console.log("Silver:", silver);
console.log("Rest:", rest);
The spread operator ... unpacks arrays. Use it to merge arrays or create copies. Array.from creates arrays from array-like objects or with a mapping function. Destructuring unpacks array values into variables. The rest pattern ...rest collects remaining elements.
Full stack: ["HTML", "CSS", "JavaScript", "Node", "Python", "Java"] Evens: [2, 4, 6, 8, 10] Gold: Aarav Silver: Priya Rest: ["Diya", "Vikram"]
find, findIndex, every, some
const students = [
  { name: "Aarav", marks: 85 },
  { name: "Priya", marks: 92 },
  { name: "Rohan", marks: 67 },
  { name: "Diya", marks: 45 }
];

// find: first student with marks > 80
const topStudent = students.find(s => s.marks > 80);
console.log("First topper:", topStudent.name);

// findIndex: index of first failing student
const failIdx = students.findIndex(s => s.marks < 50);
console.log("First fail at index:", failIdx);

// every: did everyone pass?
console.log("All passed:", students.every(s => s.marks >= 50));

// some: did anyone score above 90?
console.log("Any above 90:", students.some(s => s.marks > 90));
find returns the first element matching the condition. findIndex returns its index. every checks if ALL elements match (returns false if even one fails). some checks if ANY element matches (returns true if at least one passes).
First topper: Aarav First fail at index: 3 All passed: false Any above 90: true
flat, flatMap, and Real Data Processing
// flat: flatten nested arrays
const grades = [[85, 92], [67, 73], [91, 88]];
console.log("Flat:", grades.flat());

// flatMap: split sentences into words
const reviews = ["Great course", "Loved the projects", "Very helpful"];
const words = reviews.flatMap(r => r.split(" "));
console.log("Words:", words);

// Real data processing: student report
const classData = [
  { name: "Kavya", subjects: ["Maths", "Science"] },
  { name: "Arjun", subjects: ["English", "Maths"] }
];

const allSubjects = [...new Set(classData.flatMap(s => s.subjects))];
console.log("All unique subjects:", allSubjects);
flat() flattens one level of nesting by default. flatMap() is like calling map() then flat(1) in one step. The last example uses flatMap to get all subjects from all students, then a Set to remove duplicates, and spread to convert back to an array.
Flat: [85, 92, 67, 73, 91, 88] Words: ["Great", "course", "Loved", "the", "projects", "Very", "helpful"] All unique subjects: ["Maths", "Science", "English"]

Common Mistakes

Sorting Numbers Without a Compare Function

const nums = [40, 100, 1, 5, 25];
nums.sort();
console.log(nums); // [1, 100, 25, 40, 5] - Wrong!
Numbers are sorted as strings. 100 comes before 25 because "1" < "2" alphabetically.
const nums = [40, 100, 1, 5, 25];
nums.sort((a, b) => a - b);
console.log(nums); // [1, 5, 25, 40, 100] - Correct!
The default sort() converts elements to strings and sorts them alphabetically. For numbers, you MUST pass a compare function: (a, b) => a - b for ascending order. This is one of the most common JavaScript gotchas.

Confusing map and forEach

const nums = [1, 2, 3];
const doubled = nums.forEach(n => n * 2);
console.log(doubled); // undefined!
forEach returns undefined. It does not create a new array.
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
console.log(doubled); // [2, 4, 6]
forEach is for side effects (like logging or DOM updates). It always returns undefined. map is for transforming data - it returns a new array with the results. Use map when you need a new array, forEach when you just want to do something with each element.

Forgetting That sort Mutates the Original Array

const original = [3, 1, 4, 1, 5];
const sorted = original.sort((a, b) => a - b);
console.log(sorted);   // [1, 1, 3, 4, 5]
console.log(original); // [1, 1, 3, 4, 5] - Also changed!
sort modifies the original array. Both variables point to the same sorted array.
const original = [3, 1, 4, 1, 5];
const sorted = [...original].sort((a, b) => a - b);
console.log(sorted);   // [1, 1, 3, 4, 5]
console.log(original); // [3, 1, 4, 1, 5] - Unchanged!
sort() modifies the array in place. If you need to keep the original, spread it into a new array first: [...original].sort(). Methods like map, filter, and slice create new arrays, but sort, splice, push, and pop mutate the original.

Using Wrong Initial Value in reduce

const nums = [1, 2, 3];
const product = nums.reduce((acc, n) => acc * n);
console.log(product); // 6 (works here)

const empty = [];
const sum = empty.reduce((acc, n) => acc + n);
// TypeError: Reduce of empty array with no initial value
Without an initial value, reduce fails on empty arrays.
const nums = [1, 2, 3];
const product = nums.reduce((acc, n) => acc * n, 1);
console.log(product); // 6

const empty = [];
const sum = empty.reduce((acc, n) => acc + n, 0);
console.log(sum); // 0 (no error)
Always provide an initial value as the second argument to reduce. Without it, reduce uses the first element as the initial value, which fails on empty arrays. For sum, use 0. For product, use 1. For string concatenation, use "".

Expecting indexOf to Work with Objects

const students = [{ name: "Aarav" }, { name: "Priya" }];
console.log(students.indexOf({ name: "Aarav" })); // -1 (not found!)
indexOf compares by reference, not by value. Two different objects with the same content are not equal.
const students = [{ name: "Aarav" }, { name: "Priya" }];
const index = students.findIndex(s => s.name === "Aarav");
console.log(index); // 0
In JavaScript, objects are compared by reference (memory address), not by their content. { name: "Aarav" } === { name: "Aarav" } is false because they are two different objects. Use findIndex with a callback to search by property values.

Summary

  • Arrays are ordered collections of values, accessed by zero-based index. They can hold any data type and grow/shrink dynamically.
  • push/pop add/remove from the end. unshift/shift add/remove from the start. splice can insert, remove, or replace at any position.
  • slice creates a new array from a portion without modifying the original. splice modifies the original array in place.
  • map transforms every element and returns a new array. Use it when you need to convert data (like adding tax to prices or extracting names).
  • filter creates a new array with only elements that pass a test. Use it to select or exclude items based on a condition.
  • reduce processes all elements into a single value. Always provide an initial value as the second argument to avoid errors with empty arrays.
  • sort modifies the array in place. For numbers, always use a compare function: (a, b) => a - b for ascending. Spread into a copy to preserve the original.
  • find returns the first matching element. findIndex returns its index. every checks if ALL match. some checks if ANY match.
  • The spread operator [...arr] copies arrays, merges arrays, and converts iterables to arrays. Array.from creates arrays from array-like objects.
  • Method chaining (filter then sort then map) is a powerful pattern for data processing. Each method returns a new array, enabling the chain.
  • Destructuring unpacks array values into variables. The rest pattern (...rest) collects remaining elements into a new array.

Ready to Practice?

Test your understanding with 50+ practice questions on this topic.

Go to Practice Questions

Want to learn web development with a live mentor?

Explore our Frontend Masterclass