Arrays

Lesson 5 of 10

On this page

An array is an ordered list of values — a shopping cart, a list of names, a set of scores. It’s one of the most-used data structures in JavaScript, and it comes with a rich set of built-in tools for reading, changing, and transforming the values it holds.

Creating and reading arrays

You create an array with square brackets, separating each value with a comma. Each value gets a numeric index starting at 0:

const colors = ["red", "green", "blue"];

colors[0];      // "red"  — first item
colors[2];      // "blue" — third item
colors.length;  // 3      — how many items it holds
colors.at(-1);  // "blue" — last item, without doing length - 1

Adding and removing items

The most common changes happen at the end of the array:

const queue = ["Alice", "Bob"];

queue.push("Carol");   // adds to the end   → ["Alice", "Bob", "Carol"]
queue.pop();           // removes from the end, returns it → "Carol"
queue.unshift("Zara"); // adds to the start → ["Zara", "Alice", "Bob"]
queue.shift();         // removes from the start, returns it → "Zara"

Looping over an array

for...of is the most common, readable way to visit every item in an array:

const colors = ["red", "green", "blue"];

for (const color of colors) {
    console.log(color);
}
// "red"
// "green"
// "blue"

.forEach does the same thing in method form, handing each item to a function you provide:

colors.forEach((color) => console.log(color));

Transforming arrays: map and filter

These two methods are everywhere in modern JavaScript — they each take a function and return a brand new array, leaving the original untouched:

const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map((n) => n * 2);
// [2, 4, 6, 8, 10]

const evens = numbers.filter((n) => n % 2 === 0);
// [2, 4]

const labeled = numbers.map((n) => `Number ${n}`);
// ["Number 1", "Number 2", ...]

.map transforms every item into something new; .filter keeps only the items that pass a test (a function that returns true or false).

Destructuring — unpacking values by position

Destructuring lets you pull values out of an array straight into named variables, which is far more readable than indexing one at a time:

const [first, second] = ["Alice", "Bob", "Carol"];
console.log(first);  // "Alice"
console.log(second); // "Bob"

const [leader, ...rest] = ["Alice", "Bob", "Carol"];
console.log(leader); // "Alice"
console.log(rest);   // ["Bob", "Carol"]

Spreading — copying and combining arrays

The ... spread syntax expands an array’s items in place — perfect for copying an array or merging several together without mutating the originals:

const base = [1, 2, 3];
const copy = [...base];             // [1, 2, 3] — a new, independent array
const combined = [...base, 4, 5];   // [1, 2, 3, 4, 5]
const merged = [...base, ...[9, 9]]; // [1, 2, 3, 9, 9]

Less common, but good to know

const numbers = [4, 1, 7, 3];

numbers.includes(7);              // true
numbers.find((n) => n > 5);       // 7 — first match
numbers.some((n) => n > 5);       // true  — does at least one match?
numbers.every((n) => n > 0);      // true  — do all of them match?
numbers.sort((a, b) => a - b);    // [1, 3, 4, 7] — sorted ascending
numbers.reduce((total, n) => total + n, 0); // 15 — combine into one value

.reduce is the most flexible — and least intuitive at first glance — of the bunch. It walks through the array building up a single result (here, a running total that starts at 0), which makes it useful once .map and .filter aren’t quite enough on their own.

The old way of doing things

Before for...of and the array methods above were common, loops over arrays were written with a counter and the array’s length:

var colors = ["red", "green", "blue"];

for (var i = 0; i < colors.length; i++) {
    console.log(colors[i]);
}

This works, but it introduces a counter variable (i) you have to manage yourself, and it’s easy to get the start, end, or increment slightly wrong — a classic source of “off-by-one” bugs. for...of removes the counter entirely, and .map/.filter/.reduce go a step further by describing what you want (“a new array of doubled numbers”) rather than how to loop to get it — which is why they’re the style you’ll see in most JavaScript written today. You’ll still come across the classic counting for loop — the Loops lesson later in this series covers when it’s still the right tool.