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
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
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
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]
What to read next
- DOM manipulation — Use your knowledge of arrays and objects to manipulate HTML