Skip to main content

Arrays

An ordered collection of elements.

Creating and accessing arrays

// Creating an array
const numbers = [1, 2, 3, 4, 5];

// Accessing elements (indexes start at 0)
console.log(numbers[0]); // 1
console.log(numbers[2]); // 3

// Length of the array
console.log(numbers.length); // 5

Accessing the last element

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

// Traditional: use length
console.log(numbers[numbers.length - 1]); // 5

// Array.at() (ES2022): a negative index counts from the end
console.log(numbers.at(-1)); // 5 (the last element)
console.log(numbers.at(-2)); // 4 (the second from the end)

Manipulating arrays

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

// Add / remove an element at the end
numbers.push(6); // [1, 2, 3, 4, 5, 6]
numbers.pop(); // [1, 2, 3, 4, 5] (takes out 6)

// Add / remove an element at the beginning
numbers.unshift(0); // [0, 1, 2, 3, 4, 5]
numbers.shift(); // [1, 2, 3, 4, 5] (takes out 0)

// Get a subarray (does not change the original array)
console.log(numbers.slice(1, 4)); // [2, 3, 4]

// Concatenate arrays
console.log(numbers.concat([6, 7])); // [1, 2, 3, 4, 5, 6, 7]

// Convert array elements to a string
console.log(numbers.join(", ")); // 1, 2, 3, 4, 5
Mutating and non-mutating methods

push / pop / shift / unshift / splice / sort change the original array directly (mutating). On the other hand, slice / concat / map / filter return a new array without changing the original (non-mutating). When you want to keep the original data, choose non-mutating methods.

Checking for the existence of an element

const fruits = ["Apple", "Banana", "Orange"];

// includes: returns true / false for whether it's contained (highly readable)
console.log(fruits.includes("Banana")); // true

// indexOf: returns the position. -1 if it doesn't exist
console.log(fruits.indexOf("Banana")); // 1
console.log(fruits.indexOf("Grape")); // -1
Choosing between includes and indexOf

If you only want to know "whether it's contained," includes() makes the intent clearer. Use indexOf() when you need the position. Note there's also this difference: indexOf(NaN) always returns -1 (it can't find NaN), whereas includes(NaN) can check correctly.

Higher-order functions for arrays

These are methods that take a function as an argument, letting you write loop processing concisely.

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

// map: apply a function to each element to create a new array
console.log(data.map(item => item * 2)); // [2, 4, 6, 8, 10]

// filter: create a new array of only the elements that match a condition
console.log(data.filter(item => item % 2 === 0)); // [2, 4]

// reduce: accumulate the array's elements into a single value
console.log(data.reduce((acc, curr) => acc + curr, 0)); // 15

// forEach: run a function for each element (no return value)
data.forEach(item => console.log(`Item: ${item}`));

// find: return the first "element" that matches a condition
console.log(data.find(item => item > 3)); // 4

// findIndex: return the "position" of the first element that matches a condition
console.log(data.findIndex(item => item > 3)); // 3

// some: whether at least one satisfies the condition
console.log(data.some(item => item > 4)); // true

// every: whether all satisfy the condition
console.log(data.every(item => item > 0)); // true
Beginner-friendly explanation

Using higher-order functions, you can write loop processing declaratively. In particular, map (transform), filter (narrow down), and reduce (aggregate) are the basics of data processing. These are non-mutating, so the original array stays as is.

Array destructuring (ES6)

const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
  • DOM manipulation — Use your knowledge of arrays and objects to manipulate HTML