Skip to the content

JavaScript arrays and their common methods

Last updated: By Lukas BrandtLesson 7 of 114 min read

A variable holds one value. An array holds a whole list of them, in order, under a single name. Arrays turn up everywhere in browser code: the links in a menu, the questions in a quiz, the rows a server sends back. Learn a dozen of their methods and most list handling shrinks to a line or two.

Creating and reading

const parts = ['CPU', 'cooler', 'thermal paste', 'screwdriver'];

console.log(parts.length);   // 4
console.log(parts[0]);       // "CPU"
console.log(parts[3]);       // "screwdriver"
console.log(parts[4]);       // undefined
console.log(parts.at(-1));   // "screwdriver", counted from the end

Square brackets, items separated by commas. Positions, called indexes, start at 0, so the last item sits at length - 1. Asking for an index past the end does not cause an error; you just get undefined. The at() method also accepts negative numbers, which makes it the easy way to grab the last item.

An array can hold anything, mixed freely: numbers, strings, objects, other arrays, even elements. Declaring it with const stops you from replacing the whole array, but you can still change what is inside. parts.push('fan') is fine, while parts = [] throws a TypeError.

Adding and removing

These methods change the array in place:

  • push(item) adds to the end, and pop() removes the last item and returns it.
  • unshift(item) adds to the start, and shift() removes the first item and returns it.
  • splice(start, count) removes count items beginning at index start. It can insert new items in the same call: parts.splice(1, 1, 'tower cooler') swaps out the second item.
const queue = ['repaste', 'clean filters'];

queue.push('update BIOS');   // ['repaste', 'clean filters', 'update BIOS']
const next = queue.shift();  // next is 'repaste'
queue.splice(0, 1);          // removes 'clean filters'

console.log(queue);          // ['update BIOS']

Searching

  • includes(value) answers yes or no: parts.includes('cooler') is true.
  • indexOf(value) gives the position, or -1 when the value is missing.
  • find(test) returns the first item for which your test function returns true, or undefined. findIndex(test) returns that item's position instead.

The -1 from indexOf is behind a classic bug. if (parts.indexOf('CPU')) looks like a yes or no question, but the CPU sits at index 0, which is falsy, so the block is skipped; and a missing item gives -1, which is truthy, so the block runs. The test is wrong both ways. When you only need a yes or no, use includes.

find comes into its own with an array of objects, which is how structured data is usually stored:

const chips = [
  { model: 'E5450', fsb: 333, multiplier: 9 },
  { model: 'E5420', fsb: 333, multiplier: 7.5 },
  { model: 'X5470', fsb: 333, multiplier: 10 }
];

const pick = chips.find((chip) => chip.model === 'E5420');
console.log(pick.multiplier);  // 7.5

Each object groups related values under named keys, and chip.model reads one of them. The test function is an arrow function from the earlier lessons: it receives one item at a time and returns true or false. The mini quiz at the end of this course keeps its questions in exactly this shape.

Transforming without touching the original

These methods leave the original array alone and return something new:

  • map(fn) runs a function on every item and collects the results in a new array of the same length.
  • filter(fn) keeps only the items for which the function returns true.
  • slice(start, end) copies a section, up to but not including end.
  • join(separator) glues all items into one string.
const speeds = chips.map((chip) => chip.fsb * chip.multiplier);
// [2997, 2497.5, 3330]

const nineAndUp = chips.filter((chip) => chip.multiplier >= 9);
// the E5450 and X5470 objects

const names = chips.map((chip) => chip.model).join(', ');
// "E5450, E5420, X5470"

The last line chains two methods and reads left to right: take the chips, turn each into its model name, join the names with a comma and a space. Combine filter with the conditions from the if statements lesson and you can narrow a list by almost any rule.

Sorting, carefully

sort() changes the array in place, and by default it compares items as text. [10, 9, 1].sort() gives [1, 10, 9], because the string '10' comes before '9', the same trap as comparing strings with <. For numbers, pass a compare function:

const temps = [61, 48, 72, 55];
temps.sort((a, b) => a - b);   // [48, 55, 61, 72]

The function receives two items and returns a negative number when a should come first, a positive number when b should, and 0 for a tie. Subtracting does all three in one step; b - a sorts from high to low instead. If you still need the original order, sort a copy: temps.slice().sort((a, b) => a - b). Current browsers also offer toSorted(), which returns a sorted copy directly.

NodeLists are not arrays

The NodeList you get from querySelectorAll, covered when accessing elements, has length and forEach but no map or filter. Convert it with Array.from when you need them:

const noteTexts = Array.from(document.querySelectorAll('.note'))
  .map((note) => note.textContent);
Parts links can earn us a commission. As an Amazon Associate I earn from qualifying purchases.

Try it

In the online HTML editor, put an empty <ul id="parts-list"></ul> on a page. Use map to turn every entry of parts into an <li> string, join('') the results and assign the string to the list's innerHTML. Then push one more part, sort() the array alphabetically and render it again. Strings you wrote yourself are safe in innerHTML; the next lesson builds the same list with createElement, which is the better habit for anything a visitor typed.