Skip to content
aviral gupta

// B5.1 · ~30 min · Beginner

Arrays and their methods

After this lesson you read, change, search, copy and sort an array, and know which methods change it.

Lesson 1 of 5 in B5 Arrays, objects and JSON

Start of the module

You will be able to

  • Read an array by index, length and at(-1), and add or remove items with push, pop, shift and unshift
  • Search an array with includes, indexOf, find and findIndex, copy part of it with slice, change it with splice, and join it
  • Sort numbers with a compare function, and tell the methods that change the array from those that return a new one
  1. Warm-up · Activity 1 of 7

    Warm-up: what does this print?

    const colours = ["red", "green", "blue"];
    console.log(colours[1]);
  2. Predict · Activity 2 of 7

    Predict before you read on: what does this print?

    console.log([10, 1, 5, 100].sort());
  3. Practice · Activity 3 of 7

    Fill in the gap so that the program prints the last item, cherry, counting from the end of the array.

    const fruits = ["apple", "banana", "cherry"];
    console.log(fruits.____);
    console.log(fruits.);
  4. Practice · Activity 4 of 7

    Match each method to what it does.

  5. Practice · Activity 5 of 7

    What does this print?

    const a = [1, 2, 3, 4, 5];
    const b = a.splice(1, 2);
    console.log(a, b);
  6. Brain teaser · Activity 6 of 7

    Brain teaser. The program sorts, then adds to sorted. What does it print?

    const scores = [40, 9, 100];
    const sorted = scores.sort((a, b) => a - b);
    sorted.push(1);
    console.log(scores);
  7. Apply · Activity 7 of 7

    Mini-task: a queue at a counter. Start with three names in an array. Add one name at the end and one at the front, then print the length and the last name with at(-1). Serve the first person with shift and print who was served. Someone leaves: find their position with indexOf and remove them with splice. Finally print an alphabetical copy with toSorted next to the queue itself, to show that the queue kept its order.

    Check your work against this list

Build it yourself

Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.

Worked example

A to-do list and some scores

One program that uses most of the lesson: it reads a to-do list by index and from the end, adds and removes tasks, searches it, then copies and sorts a list of scores. Watch the last three lines: the default sort puts 100 first, the compare function fixes that, and scores itself never changes, because toSorted returns a copy.

main.js

// A to-do list and some scores: read, change, search, sort.
const tasks = ["wash", "shop", "cook"];
console.log(tasks[0], tasks.length, tasks.at(-1));

tasks.push("read");
const done = tasks.shift();
console.log(done, tasks);

console.log(tasks.includes("cook"), tasks.indexOf("cook"), tasks.indexOf("swim"));

const scores = [40, 100, 9, 25];
console.log(scores.find((s) => s > 30), scores.findIndex((s) => s > 30));
console.log(scores.slice(1, 3), scores.join(" | "));

console.log(scores.toSorted());
console.log(scores.toSorted((a, b) => a - b));
console.log(scores);

Run it with

node main.js

Output

wash 3 cook
wash [ 'shop', 'cook', 'read' ]
true 1 -1
40 0
[ 100, 9 ] 40 | 100 | 9 | 25
[ 100, 25, 40, 9 ]
[ 9, 25, 40, 100 ]
[ 40, 100, 9, 25 ]
  • shift returned "wash" and removed it, so tasks now starts with "shop".
  • indexOf gives -1 for "swim", which is not in the list.
  • find returns the first score above 30, which is 40 at index 0, not the largest one.
  • toSorted() with no compare function sorts as strings, so 100 comes before 25.
  • The last line shows scores unchanged after both toSorted calls.
Change it and run it

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Exercises

Exercise 1 of 2

Sorted prices, original untouched

sortedPrices(prices) should return the prices sorted from lowest to highest, as a new array, and leave the array it was given in its old order. The starter has two bugs: it sorts 100 before 12, and it changes the caller's array. Fix both. Keep the word export in front of the function, as in module B4.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Hints
  1. Hint 1

    Run the tests: [12, 5, 100] comes back as [100, 12, 5]. Why does 100 come first?

  2. Hint 2

    Numbers need a compare function: (a, b) => a - b.

  3. Hint 3

    sort changes the array it is called on. Which method returns a sorted copy instead?

  4. Hint 4

    return prices.toSorted((a, b) => a - b);

Show a solution

One way to solve it. Yours can look different and still pass the checks.

// Return a new array with the prices from lowest to highest.
export function sortedPrices(prices) {
  return prices.toSorted((a, b) => a - b);
}
Run it on your computer

Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.js

// Return a new array with the prices from lowest to highest.
export function sortedPrices(prices) {
  return prices.sort();
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {sortedPrices} from './main.js';

test('Sorts numbers by size, not as text', () => {
  const got = sortedPrices([12, 5, 100]);
  assert.deepEqual(got, [5, 12, 100], `sortedPrices([12, 5, 100]) returned ${JSON.stringify(got)}, expected [5,12,100]`);
});

test('Leaves the array it was given unchanged', () => {
  const prices = [3.5, 1.25, 2];
  sortedPrices(prices);
  assert.deepEqual(prices, [3.5, 1.25, 2], `after the call the array was ${JSON.stringify(prices)}, expected it to stay [3.5,1.25,2]`);
});

test('Returns an empty array for no prices', () => {
  const got = sortedPrices([]);
  assert.deepEqual(got, [], `sortedPrices([]) returned ${JSON.stringify(got)}, expected []`);
});

package.json

{
  "type": "module"
}

package.json tells Node.js that the .js files are modules; keep it in the folder.

Run the program:

node main.js

Run the checks (needs learnrun.js in the same folder):

node --test
Download learnrun.js

Exercise 2 of 2

Remove an item, if it is there

removeItem(list, item) should remove the first item equal to item from the list itself and return true. When the item is not in the list, it must leave the list exactly as it is and return false. The starter works for items that are there, but it damages the list when the item is missing. Find out why and fix it.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Hints
  1. Hint 1

    Run the tests: removing "jam" removes "bread". What does indexOf give for a missing item?

  2. Hint 2

    indexOf gives -1, and splice(-1, 1) counts from the end: it removes the last item.

  3. Hint 3

    Check the index before you splice: if it is -1, return false and leave the list alone.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

// Remove the first item equal to item from list. Return true if one was removed.
export function removeItem(list, item) {
  const index = list.indexOf(item);
  if (index === -1) {
    return false;
  }
  list.splice(index, 1);
  return true;
}
Run it on your computer

Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.js

// Remove the first item equal to item from list. Return true if one was removed.
export function removeItem(list, item) {
  const index = list.indexOf(item);
  list.splice(index, 1);
  return true;
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {removeItem} from './main.js';

test('Removes an item that is in the list', () => {
  const list = ['tea', 'milk', 'bread'];
  const got = removeItem(list, 'milk');
  assert.equal(got, true, `removeItem returned ${got}, expected true`);
  assert.deepEqual(list, ['tea', 'bread'], `the list is ${JSON.stringify(list)}, expected ["tea","bread"]`);
});

test('Leaves the list alone when the item is missing', () => {
  const list = ['tea', 'milk', 'bread'];
  const got = removeItem(list, 'jam');
  assert.equal(got, false, `removeItem returned ${got} for a missing item, expected false`);
  assert.deepEqual(list, ['tea', 'milk', 'bread'], `the list became ${JSON.stringify(list)}, expected it unchanged`);
});

test('Removes only the first of two equal items', () => {
  const list = ['a', 'b', 'a'];
  removeItem(list, 'a');
  assert.deepEqual(list, ['b', 'a'], `the list is ${JSON.stringify(list)}, expected ["b","a"]`);
});

package.json

{
  "type": "module"
}

package.json tells Node.js that the .js files are modules; keep it in the folder.

Run the program:

node main.js

Run the checks (needs learnrun.js in the same folder):

node --test
Download learnrun.js

Common mistakes

A method from another language

const tasks = ["wash", "shop", "cook"];
if (tasks.contains("cook")) {
  console.log("Dinner is planned");
}

What Node.js prints

TypeError: tasks.contains is not a function

Why, and the fix

Arrays in JavaScript have no contains method, so tasks.contains is undefined, and calling undefined is a TypeError. The method is called includes: tasks.includes("cook") returns true or false. When the message says that a method is not a function, check its spelling and whether arrays have it at all.

Expecting push to return the array

const tasks = ["wash", "shop"];
const more = tasks.push("cook");
console.log(more.at(-1));

What Node.js prints

TypeError: more.at is not a function

Why, and the fix

push changes tasks itself and returns the new length, here the number 3. more is a number, and numbers have no at method. Use the array you pushed onto: tasks.at(-1) is "cook". unshift also returns the new length; pop and shift return the item they removed.

Using what find did not find

const words = ["apple", "banana", "cherry"];
const word = words.find((w) => w.startsWith("z"));
console.log(word.toUpperCase());

What Node.js prints

TypeError: Cannot read properties of undefined (reading 'toUpperCase')

Why, and the fix

No word starts with "z", so find returns undefined, and undefined has no methods. The message names the method it tried to read. Check the result before you use it: if (word !== undefined) { … }, or print a message when nothing was found.

JavaScript in the browser: your browser’s own engine, in a sandboxed worker. Syntax errors are located with acorn 8.18.0, MIT. Licence and source

Exit ticket

5 questions, no hints. Score 80% or more to complete the lesson.

Finish every activity above to unlock the exit ticket.

Report a problem

Spotted something wrong or unclear? Say what, and it will be checked and fixed.

#

At least 20 characters.

Only if you want a reply.

Key ideas

An ordered list of values

An array literal lists values in square brackets: const tasks = ["wash", "shop", "cook"];. Each item has an index, starting at 0, so tasks[0] is "wash". length is the number of items, so the last index is length - 1. An index that does not exist gives undefined, not an error. at(-1) counts back from the end: tasks.at(-1) is "cook". push adds items to the end and pop removes the last one; unshift adds to the front and shift removes the first. pop and shift return the item they removed, but push and unshift return the new length, not the array. const stops you replacing the array, not changing its items.

Search, copy and cut

includes("cook") answers true or false. indexOf gives the first position of a value, or -1 when it is not there. find takes a function, as in lesson B4.1, and returns the first item for which it returns true, or undefined; findIndex returns that item's position, or -1. slice(1, 3) copies the items from index 1 up to, but not including, index 3 into a new array and leaves the original alone. splice(1, 2) removes two items starting at index 1 from the array itself and returns them. join(" | ") turns the items into one string with the separator between them.

Sorting, and who changes the array

sort() without arguments compares items as strings, so [40, 100, 9, 25].sort() gives [ 100, 25, 40, 9 ]: "1" comes before "2". For numbers, pass a compare function: (a, b) => a - b sorts ascending, b - a descending. sort changes the array itself and returns that same array. push, pop, shift, unshift, splice, sort and reverse all change the array; slice, join, includes, indexOf, find, at and concat leave it alone. toSorted() and toReversed() are the copying versions: they return a new array and leave the original unchanged. MDN marks both "Baseline Widely available": every current major browser has had them since July 2023.

Sources

Last reviewed October 3, 2026