Warm-up · Activity 1 of 7
Warm-up: what does this print?
const colours = ["red", "green", "blue"];
console.log(colours[1]);// B5.1 · ~30 min · Beginner
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
You will be able to
Warm-up · Activity 1 of 7
const colours = ["red", "green", "blue"];
console.log(colours[1]);Predict · Activity 2 of 7
console.log([10, 1, 5, 100].sort());Practice · Activity 3 of 7
const fruits = ["apple", "banana", "cherry"];
console.log(fruits.____);Practice · Activity 4 of 7
Practice · Activity 5 of 7
const a = [1, 2, 3, 4, 5];
const b = a.splice(1, 2);
console.log(a, b);Brain teaser · Activity 6 of 7
const scores = [40, 9, 100];
const sorted = scores.sort((a, b) => a - b);
sorted.push(1);
console.log(scores);Apply · Activity 7 of 7
Check your work against this list
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
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.jsOutput
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 ]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.
Exercise 1 of 2
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.
Run the tests: [12, 5, 100] comes back as [100, 12, 5]. Why does 100 come first?
Numbers need a compare function: (a, b) => a - b.
sort changes the array it is called on. Which method returns a sorted copy instead?
return prices.toSorted((a, b) => a - b);
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);
}
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.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsExercise 2 of 2
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.
Run the tests: removing "jam" removes "bread". What does indexOf give for a missing item?
indexOf gives -1, and splice(-1, 1) counts from the end: it removes the last item.
Check the index before you splice: if it is -1, return false and leave the list alone.
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;
}
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.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsconst tasks = ["wash", "shop", "cook"];
if (tasks.contains("cook")) {
console.log("Dinner is planned");
}
What Node.js prints
TypeError: tasks.contains is not a functionWhy, 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.
const tasks = ["wash", "shop"];
const more = tasks.push("cook");
console.log(more.at(-1));
What Node.js prints
TypeError: more.at is not a functionWhy, 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.
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
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.