Ad – 728Γ—90
πŸ“¦ Data Structures

JavaScript Arrays – The Complete Guide

Arrays are the most versatile data structure in JavaScript. They store ordered lists of values, come packed with powerful built-in methods, and are central to nearly every program you write. This guide covers everything from basic creation to advanced iteration patterns.

⏱️ 28 min read 🎯 Intermediate πŸ“… Updated 2026

Creating Arrays

JavaScript gives you two primary ways to create arrays: the array literal syntax (preferred) and the Array() constructor.

JavaScript
// Array literal – the preferred way
const fruits = ['apple', 'banana', 'cherry'];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, 'hello', true, null, { id: 1 }];
const empty = [];

// Array() constructor
const zeros = new Array(3);        // [empty Γ— 3] β€” sparse array
const explicit = new Array(1, 2, 3); // [1, 2, 3]

// Array.of() – always creates elements, never a sparse array
const safe = Array.of(3);          // [3]  (not [empty Γ— 3])

// Array.from() – from iterables or array-like objects
const fromString = Array.from('hello');      // ['h','e','l','l','o']
const fromSet    = Array.from(new Set([1, 2, 2, 3])); // [1, 2, 3]
const mapped     = Array.from({ length: 5 }, (_, i) => i * 2);
// [0, 2, 4, 6, 8]

console.log(fruits.length); // 3
πŸ’‘
Prefer Array Literals

Always use [] instead of new Array(). The constructor behaves inconsistently β€” new Array(3) creates a sparse array with 3 empty slots, not an array containing the number 3.

Accessing Elements

Array elements are accessed by their zero-based index. ES2022 introduced Array.prototype.at() which supports negative indices.

JavaScript
const colors = ['red', 'green', 'blue', 'yellow'];

// Bracket notation (zero-based index)
console.log(colors[0]);   // 'red'
console.log(colors[2]);   // 'blue'
console.log(colors[10]);  // undefined (no error)

// Negative indices with .at()
console.log(colors.at(-1));  // 'yellow' (last element)
console.log(colors.at(-2));  // 'blue'

// Array length
console.log(colors.length);  // 4

// Last element (classic approach)
console.log(colors[colors.length - 1]); // 'yellow'

// Destructuring (preview)
const [first, second] = colors;
console.log(first, second); // 'red' 'green'
β–Ά Output
red
blue
undefined
yellow
blue
4
yellow
red green

Adding and Removing Elements

JavaScript arrays are mutable. Several methods let you add or remove elements from either end or anywhere in the middle.

JavaScript
const stack = ['a', 'b', 'c'];

// End of array
stack.push('d', 'e');   // adds to end β†’ ['a','b','c','d','e']
stack.pop();            // removes last β†’ returns 'e' β†’ ['a','b','c','d']

// Beginning of array
stack.unshift('z');     // adds to front β†’ ['z','a','b','c','d']
stack.shift();          // removes first β†’ returns 'z' β†’ ['a','b','c','d']

// splice(startIndex, deleteCount, ...itemsToInsert)
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(1, 2);        // removes 2 at index 1
console.log(removed); // [2, 3]
console.log(arr);     // [1, 4, 5]

arr.splice(1, 0, 10, 20); // insert at index 1, delete 0
console.log(arr); // [1, 10, 20, 4, 5]

// slice – returns a NEW array (does not mutate)
const sliced = arr.slice(1, 3);  // from index 1 up to (not including) 3
console.log(sliced); // [10, 20]
console.log(arr);    // unchanged: [1, 10, 20, 4, 5]
MethodWhereMutates?Returns
push(...items)EndYesNew length
pop()EndYesRemoved element
unshift(...items)StartYesNew length
shift()StartYesRemoved element
splice(i, n, ...)AnyYesRemoved elements
slice(s, e)AnyNoNew array

Searching Arrays

JavaScript provides several methods for finding elements. Choose based on what you need: the index, the element itself, or just a boolean.

JavaScript
const nums = [10, 20, 30, 20, 40];
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Carol' }
];

// indexOf / lastIndexOf – use strict equality (===)
console.log(nums.indexOf(20));      // 1 (first occurrence)
console.log(nums.lastIndexOf(20));  // 3 (last occurrence)
console.log(nums.indexOf(99));      // -1 (not found)

// includes – returns boolean
console.log(nums.includes(30));  // true
console.log(nums.includes(99));  // false

// find – returns the element (or undefined)
const bob = users.find(u => u.name === 'Bob');
console.log(bob); // { id: 2, name: 'Bob' }

// findIndex – returns the index (or -1)
const idx = users.findIndex(u => u.id === 3);
console.log(idx); // 2

// findLast / findLastIndex (ES2023)
const lastEven = nums.findLast(n => n % 2 === 0);
console.log(lastEven); // 40

Iterating Arrays

forEach, map, filter, and reduce are the four workhorses of array iteration. Each serves a distinct purpose.

JavaScript
const prices = [100, 250, 75, 320, 180];

// forEach – side effects only, returns undefined
prices.forEach((price, index) => {
  console.log(`Item ${index}: $${price}`);
});

// map – transforms each element, returns new array
const discounted = prices.map(p => p * 0.9);
console.log(discounted); // [90, 225, 67.5, 288, 162]

// filter – keeps elements where callback returns true
const expensive = prices.filter(p => p > 150);
console.log(expensive); // [250, 320, 180]

// reduce – accumulates a single value
const total = prices.reduce((sum, p) => sum + p, 0);
console.log(total); // 925

// Chaining – readable pipeline
const totalDiscountExpensive = prices
  .filter(p => p > 100)
  .map(p => p * 0.9)
  .reduce((sum, p) => sum + p, 0);
console.log(totalDiscountExpensive.toFixed(2)); // "674.10"
β–Ά Output
Item 0: $100
Item 1: $250
...
[90, 225, 67.5, 288, 162]
[250, 320, 180]
925
"674.10"

Sorting and Reversing

sort() and reverse() mutate the original array. Always provide a comparator function to sort() for numeric sorting.

JavaScript
// Default sort – converts to string, lexicographic order
[10, 9, 2, 100].sort();     // [10, 100, 2, 9] ← WRONG for numbers!

// Numeric sort with comparator
[10, 9, 2, 100].sort((a, b) => a - b);  // [2, 9, 10, 100] ascending
[10, 9, 2, 100].sort((a, b) => b - a);  // [100, 10, 9, 2] descending

// Alphabetical sort (strings already work without comparator)
['banana', 'apple', 'cherry'].sort(); // ['apple', 'banana', 'cherry']

// Case-insensitive sort
['Banana', 'apple', 'Cherry'].sort((a, b) =>
  a.toLowerCase().localeCompare(b.toLowerCase())
);
// ['apple', 'Banana', 'Cherry']

// reverse – reverses in place
const arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]

// Non-mutating sort (ES2023: toSorted, toReversed)
const original = [3, 1, 2];
const sorted = original.toSorted((a, b) => a - b);
console.log(original); // [3, 1, 2] – unchanged
console.log(sorted);   // [1, 2, 3]
πŸ’‘
Always Use a Comparator for Numbers

Without a comparator, sort() converts every element to a string first. [10, 9, 100].sort() gives [10, 100, 9] β€” not what you want. Always pass (a, b) => a - b for ascending numeric sort.

flat, flatMap, Array.from, Array.isArray

JavaScript
// flat – flattens nested arrays
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat());    // [1, 2, 3, 4, [5, 6]] – one level
console.log(nested.flat(2));   // [1, 2, 3, 4, 5, 6] – two levels
console.log(nested.flat(Infinity)); // fully flatten any depth

// flatMap – map then flat(1) in one pass (more efficient)
const sentences = ['Hello world', 'foo bar'];
const words = sentences.flatMap(s => s.split(' '));
console.log(words); // ['Hello', 'world', 'foo', 'bar']

// Array.from – converts iterables and array-likes
const nodeList = document.querySelectorAll('p'); // NodeList (array-like)
const paragraphs = Array.from(nodeList);         // real Array

// Array.from with map function
const squares = Array.from({ length: 5 }, (_, i) => (i + 1) ** 2);
console.log(squares); // [1, 4, 9, 16, 25]

// Array.isArray – reliable type check
console.log(Array.isArray([]));          // true
console.log(Array.isArray(new Array())); // true
console.log(Array.isArray('hello'));     // false
console.log(Array.isArray({ length: 3 })); // false

Multidimensional Arrays

JavaScript does not have true 2D arrays, but you can nest arrays inside arrays to simulate matrices and grids.

JavaScript
// 3x3 matrix
const matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

// Access with double indexing
console.log(matrix[1][2]); // 6 (row 1, col 2)

// Iterate with nested loops
for (let row = 0; row < matrix.length; row++) {
  for (let col = 0; col < matrix[row].length; col++) {
    process.stdout.write(matrix[row][col] + ' ');
  }
  console.log();
}

// Create a dynamic 2D array
function create2D(rows, cols, fill = 0) {
  return Array.from({ length: rows }, () => new Array(cols).fill(fill));
}
const grid = create2D(3, 4, '.');
console.log(grid);
// [
//   ['.', '.', '.', '.'],
//   ['.', '.', '.', '.'],
//   ['.', '.', '.', '.']
// ]

// Spread to copy a 2D array (shallow β€” rows are still shared)
const copy = matrix.map(row => [...row]); // deep enough for primitives
πŸ’‘
Copying Arrays with Spread

Use [...arr] or arr.slice() for a shallow copy of a 1D array. For nested arrays, use arr.map(row => [...row]) to copy each inner array too. For deeply nested structures, consider structuredClone().

Interview Questions

  • What is the difference between slice and splice?
  • Why does [1, 10, 2].sort() return [1, 10, 2] without a comparator?
  • How would you remove duplicates from an array?
  • What is the difference between map and forEach?
  • How do you flatten a deeply nested array in one line?
  • Explain reduce and give an example beyond summing numbers.

πŸ‹οΈ Practical Exercise

Given an array of product objects [{ name, price, category }]:

  1. Filter products under $50.
  2. Map to return just the product names.
  3. Sort names alphabetically.
  4. Join them into a comma-separated string.

Do all four steps as a single chained expression.

πŸ”₯ Challenge Exercise

Write a function groupBy(arr, key) that uses reduce to group an array of objects by a given property. For example, groupBy(products, 'category') should return an object where each key is a category and its value is an array of matching products. Do not use any external library.

Frequently Asked Questions

Is an array an object in JavaScript?
Yes. typeof [] returns "object". Arrays are specialised objects with numeric keys and a length property. Use Array.isArray() to reliably distinguish them from plain objects.
Can arrays hold mixed types?
Yes. A single array can hold numbers, strings, booleans, objects, functions, or other arrays. However, mixing types can make code harder to reason about β€” consider typed arrays (Int32Array, etc.) when working with large numeric data sets.
Does map mutate the original array?
No. map always returns a new array. The original remains unchanged. Only sort, reverse, push, pop, shift, unshift, splice, and fill mutate in place.
What is the difference between find and filter?
find returns the first matching element (or undefined). filter returns a new array of all matching elements. Use find when you expect a single result and performance matters.
How do I remove duplicates from an array?
The easiest way is [...new Set(arr)]. This converts the array to a Set (which only stores unique values) and spreads it back into an array.
Ad – 336Γ—280

πŸ“‹ Summary

  • Use array literals [] to create arrays; Array.from() for iterables.
  • Access elements by zero-based index; use .at(-1) for the last element.
  • push/pop work at the end; unshift/shift at the start; splice anywhere.
  • slice creates a new array without mutating the original.
  • Use indexOf/includes for primitives; find/findIndex for objects.
  • Chain filter β†’ map β†’ reduce for elegant data pipelines.
  • Always pass a comparator to sort() when sorting numbers.
  • Use flat() and flatMap() to work with nested arrays.