An array is an ordered list of values: quiz questions, products in a basket, lessons in a course. Almost every program works with lists, so arrays are one of the two data structures you will use most, alongside objects. This lesson covers creating arrays, reading and changing items, and adding and removing them.
Creating an array
Write an array as a list of values in square brackets, separated by commas:
const lessons = ["Variables", "Data types", "Operators"];
const scores = [72, 88, 95];
const empty = [];
An array can hold any mix of types, including other arrays and objects, but most arrays hold one kind of thing. A list where every item has the same shape is easier to work with.
const mixed = ["Ada", 36, true, null];
const grid = [
[1, 2],
[3, 4],
];
A trailing comma after the last item is allowed and makes adding lines tidier. Arrays are objects, so typeof gives "object"; use Array.isArray() to check for one, as lesson 4 showed.
Reading items by index
Each item has a numbered position called its index, starting from 0:
const lessons = ["Variables", "Data types", "Operators"];
console.log(lessons[0]);
// Variables
console.log(lessons[2]);
// Operators
console.log(lessons[3]);
// undefined
Reading an index that does not exist gives undefined, not an error. That makes typos quiet, so watch for unexpected undefined values.
The length property tells you how many items there are. Because indexes start at 0, the last item is at length - 1:
console.log(lessons.length);
// 3
console.log(lessons[lessons.length - 1]);
// Operators
The at() method is a neater way to read from the end. Negative numbers count backwards:
console.log(lessons.at(-1));
// Operators
console.log(lessons.at(-2));
// Data types
at() is supported in all current browsers and Node.js.
For a nested array, use two sets of brackets: grid[1][0] reads row 1, then item 0, giving 3.
Changing items
Assign to an index to replace an item:
const colours = ["red", "green", "blue"];
colours[1] = "yellow";
console.log(colours);
// ["red", "yellow", "blue"]
This works even though colours is a const. As lesson 3 explained, const stops you pointing the name at a different array, not changing the array's contents.
Avoid assigning to an index far past the end. colours[10] = "pink" creates an array of length 11 with empty slots in between, which behaves oddly with many methods.
Adding and removing at the ends
Four methods add or remove items at the start or end of an array. They all change the original array:
const queue = ["Ada", "Grace"];
queue.push("Linus"); // add to the end
console.log(queue);
// ["Ada", "Grace", "Linus"]
queue.unshift("Tim"); // add to the start
console.log(queue);
// ["Tim", "Ada", "Grace", "Linus"]
const last = queue.pop(); // remove from the end
console.log(last);
// Linus
const first = queue.shift(); // remove from the start
console.log(first);
// Tim
console.log(queue);
// ["Ada", "Grace"]
push()andunshift()return the new length. Both accept several items at once:queue.push("a", "b").pop()andshift()return the item they removed, orundefinedif the array was empty.
Adding and removing in the middle with splice
splice() removes, inserts or replaces items at any position. Its arguments are the start index, how many items to remove, then any items to insert:
const steps = ["Plan", "Build", "Ship"];
steps.splice(1, 0, "Design"); // at index 1, remove 0, insert "Design"
console.log(steps);
// ["Plan", "Design", "Build", "Ship"]
const removed = steps.splice(2, 1); // at index 2, remove 1
console.log(removed);
// ["Build"]
console.log(steps);
// ["Plan", "Design", "Ship"]
steps.splice(0, 1, "Research"); // replace the item at index 0
console.log(steps);
// ["Research", "Design", "Ship"]
splice() changes the original array and returns an array of the removed items. It is powerful but easy to misread, so add a short comment when its purpose is not obvious.
Copying part of an array with slice
slice(start, end) returns a new array containing part of the original, from start up to but not including end. The original is unchanged:
const lessons = ["Variables", "Data types", "Operators", "Strings"];
console.log(lessons.slice(1, 3));
// ["Data types", "Operators"]
console.log(lessons.slice(-2));
// ["Operators", "Strings"]
console.log(lessons.length);
// 4
slice() with no arguments copies the whole array. The names slice and splice are easy to confuse: remember that splice has an extra letter because it does extra work and changes the array.
Mutating versus non-mutating methods
Some array methods change, or mutate, the original array. Others return a new array or value and leave the original alone. Knowing which is which prevents a whole class of bugs, especially when an array is shared by several parts of your program.
| Mutates the original | Returns something new |
|---|---|
push, pop, shift, unshift | slice |
splice | concat |
sort, reverse | toSorted, toReversed, toSpliced |
fill | with |
The newer methods in the right-hand column, such as toSorted(), return changed copies. They are supported in all current browsers and Node.js 20+:
const original = [3, 1, 2];
const sorted = original.toSorted();
console.log(sorted);
// [1, 2, 3]
console.log(original);
// [3, 1, 2]
Lesson 22 covers sorting properly, and lesson 40 explains why accidental mutation causes bugs.
Joining arrays
concat() joins arrays into a new one:
const frontEnd = ["HTML", "CSS"];
const scripting = ["JavaScript"];
console.log(frontEnd.concat(scripting));
// ["HTML", "CSS", "JavaScript"]
You will often see the spread syntax [...frontEnd, ...scripting] used for the same job. Lesson 23 covers it.
join() turns an array into a string, with a separator of your choice:
console.log(frontEnd.join(" and "));
// HTML and CSS
Finding values
const tags = ["html", "css", "javascript"];
console.log(tags.includes("css"));
// true
console.log(tags.indexOf("javascript"));
// 2
console.log(tags.indexOf("python"));
// -1
includes()returnstrueorfalse. Use it when you only need to know whether a value is there.indexOf()returns the first index of the value, or-1.
Both compare with strict equality, so [1, 2].includes("1") is false. One difference: includes() can find NaN and indexOf() cannot.
To find an object in an array by one of its properties, such as a quiz question by its id, you need find() or findIndex(), which take a callback. Lesson 22 covers them.
Looping over an array
As lesson 9 showed, for...of is the simplest way to visit every item:
const basket = [4.99, 12.5, 3];
let total = 0;
for (const price of basket) {
total += price;
}
console.log(total.toFixed(2));
// 20.49
Emptying an array
To clear a let array, assign a new empty array. To clear a const array in place, set its length to 0:
const items = [1, 2, 3];
items.length = 0;
console.log(items);
// []
Summary
- Arrays are ordered lists written in square brackets, with indexes starting at 0.
- Read items with
array[index]orarray.at(-1)for the end; missing indexes giveundefined. push,pop,unshiftandshiftadd and remove at the ends;spliceworks anywhere. All of them change the original.slice,concat,toSortedand similar methods return new arrays and leave the original alone.includes()checks whether a value is present;indexOf()gives its position or-1.- Loop over arrays with
for...of.