Javascript · Functions (Advanced)
Callbacks (Intro)
The full text of this chapter, to read or revisit. To practise, do the exercises.
▶ Do the exercisesExercise 1 — What Is a Callback?
In the previous chapter, you passed a function to another function. This has a name: the function you pass is a callback.
Here's a classic example: `repeat` takes a number and an action, and runs that action as many times as asked.
function repeat(times, action) {
for (let i = 0; i < times; i++) {
action();
}
}
const cheer = () => console.log("Go Pyrochu!");
repeat(3, cheer);
`repeat` doesn't know what `action` does. It only knows when to call it. That separation is the whole point: the same `repeat` works with any action.
Exercise 2 — Callbacks With Parameters
The receiving function can pass arguments to the callback when it calls it. Here each member of the team is handed to the callback one by one:
function forEachMember(team, action) {
for (let cdm of team) {
action(cdm);
}
}
const greet = (name) => console.log("Hello " + name + "!");
forEachMember(["Aquachu", "Zap"], greet);
Exercise 3 — Quiz: Who Calls Whom?
In `repeat(3, cheer)`, which statement is true?
Options
• repeat calls cheer three times
• cheer calls repeat three times
• cheer runs once, before repeat
• Neither function runs
Hint : The callback is handed over, then called from inside the other function.
Exercise 4 — Repeat With a Counter
Complete `countdown` so it passes the current number to the callback, then use `show` as the callback.
function countdown(start, action) {
for (let n = start; n > 0; n--) {
action(____);
}
}
const show = (n) => console.log(n + "...");
countdown(3, ____);
Options: n show start show() action
Hint : Pass the loop variable to the callback, and pass the function without calling it.
Exercise 5 — Using the Callback's Result
A callback can return a value, and the receiving function can use it. Here the callback decides which members count:
function countIf(values, test) {
let count = 0;
for (let v of values) {
if (test(v)) {
count++;
}
}
return count;
}
const levels = [3, 12, 7, 15];
const isHigh = (level) => level >= 10;
console.log(countIf(levels, isHigh));
`countIf` doesn't know what "high" means. The callback does. Swap it for another test and the same function counts something else:
Exercise 6 — Quiz: Counting With a Callback
What does this code print?
function countIf(values, test) {
let count = 0;
for (let v of values) {
if (test(v)) {
count++;
}
}
return count;
}
const isSmall = (n) => n < 5;
console.log(countIf([1, 9, 4, 6, 2], isSmall));
Options
• ```3```
• ```2```
• ```5```
• ```true```
Hint : Apply the test to each value and count the true answers.
Exercise 7 — Why Callbacks Matter
Callbacks let you write a function once and customise its behaviour at each call. Compare: without a callback, you'd need one function per case.
function transformAll(values, transform) {
const result = [];
for (let v of values) {
result.push(transform(v));
}
return result;
}
const double = (n) => n * 2;
const addTen = (n) => n + 10;
console.log(transformAll([1, 2, 3], double));
console.log(transformAll([1, 2, 3], addTen));
Coming next
JavaScript arrays have built-in functions that work exactly like `forEachMember`, `countIf` and `transformAll`. They're called `forEach`, `filter` and `map`, and they're the subject of the next class.
Exercise 8 — Custom Test
Complete `keepIf` so it adds a value to the result only when the callback says so, then count the electric moves.
function keepIf(values, test) {
const kept = [];
for (let v of values) {
if (____(v)) {
kept.____(v);
}
}
return kept;
}
const moves = ["Spark", "Splash", "Thunder"];
const isElectric = (move) => move === "Spark" || move === "Thunder";
console.log(keepIf(moves, ____).length);
Options: test push isElectric v isElectric() unshift
Hint : Inside, the callback goes by its parameter name. Outside, pass the function itself.
Exercise 9 — Callback Vocabulary
Match each term with its description.
Items to match
• Callback
• repeat(3, cheer)
• action(cdm)
• The callback's return value
Definitions
• A function passed to another function
• cheer is the callback
• Calling the callback with an argument
• Can be used by the receiving function
Exercise 10 — Quiz: Order of Output
What does this code print?
function twice(action) {
console.log("start");
action();
action();
console.log("end");
}
twice(() => console.log("hit"));
Options
• ```start```, ```hit```, ```hit```, ```end```
• ```hit```, ```hit```, ```start```, ```end```
• ```start```, ```end```, ```hit```, ```hit```
• ```start```, ```hit```, ```end```
Hint : Follow the body of twice line by line.
Exercise 11 — Team Processor
Write a generic function that runs a callback on every member of a team, then use it with two different callbacks.
Step 1: `processTeam(team, action)` calls `action` once per member, passing the member's name and its position counted from 1.
Step 2: write a callback `announce(name, position)` that prints `"position. name"`, for example `"1. Aquachu"`.
Step 3: write a callback `cheer(name, position)` that prints `"Go name!"`.
Step 4: run `processTeam` with `announce`, then with `cheer`.
1. Aquachu
2. Pyrochu
3. Zap
Go Aquachu!
Go Pyrochu!
Go Zap!
Starter code
const team = ["Aquachu", "Pyrochu", "Zap"];
// Write your functions here
// Use them here
Back to the course