JavaScript249 exercises

JavaScript Exercises with Answers

Practise JavaScript with 249 interactive exercises: multiple choice, fill-in-the-blank, output prediction and debugging. Every exercise gives instant feedback, a hint and the full solution.

Score0/ 249

1JS Introduction

Read the lesson
Fill in the blankseasyJS Introduction

Print the message "Ready!" to the console.

.("Ready!");
Predict the outputeasyJS Introduction

What does this print?

console.log(10 - 4);
console.log("10 - 4");
Multiple choiceeasyJS Introduction

Which is a JavaScript comment?

Fix the bugeasyJS Introduction

This code should print two lines, but it throws errors. Fix it.

Console.log("Good morning!");
console.log(Have a great day);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Prints "Good morning!"
  • Prints "Have a great day"
  • No errors

2Where to Put JS

Read the lesson
Fill in the blankseasyWhere to Put JS

Load app.js so it runs after the HTML is parsed.

<script ="app.js" ></script>
Multiple choicemediumWhere to Put JS

What will a plain script in the <head> get from document.querySelector("button") when the button is in the body?

Multiple choicemediumWhere to Put JS

Which attribute makes scripts run in order after parsing?

Fix the bugmediumWhere to Put JS

The script runs before the paragraph exists, so it fails. Move the script so it can find the paragraph (don't change the JavaScript itself).

<script>
  document.querySelector("#greet").textContent = "Hello from JS!";
</script>
<p id="greet">Waiting…</p>
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • The paragraph was updated
  • No errors

3Output & Console

Read the lesson
Fill in the blankseasyOutput & Console

Print a warning and an error.

console.("Battery low");
console.("Battery empty!");
Predict the outputeasyOutput & Console

What does this print?

console.log("Total: " + 4 + 6);
Multiple choicemediumOutput & Console

What is the best way to show a result to users on the page?

Fix the bugeasyOutput & Console

This should print Level: 5 and show Level 5 in the paragraph. Fix it.

const level = 5;
console.log("Level: " level);
document.querySelector("#level").textcontent = "Level " + level;
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Level: 5"
  • The paragraph says "Level 5"

4Variables (let, const)

Read the lesson
Fill in the blankseasyVariables (let, const)

Create a constant for the planet and a variable for the day count, then add one day.

 planet = "Mars";
 days = 1;
days = days + 1;
console.log(planet, days);
Predict the outputeasyVariables (let, const)

What does this print?

let x = 5;
x = x + 10;
x = x * 2;
console.log(x);
Multiple choicemediumVariables (let, const)

Which variable name is valid and follows the convention?

Predict the outputmediumVariables (let, const)

What happens?

const colors = ["red"];
colors.push("blue");
console.log(colors);
Fix the bugmediumVariables (let, const)

The counter should go from 0 to 2 and print Clicks: 2. Fix the declarations.

const clicks = 0;
clicks = clicks + 1;
let clicks = clicks + 1;
console.log("Clicks:", clicks);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Clicks: 2"
  • No errors

5Data Types

Read the lesson
Fill in the blankseasyData Types

Complete the comments with each value's typeof result.

typeof "42"   // ""
typeof 42     // ""
typeof true   // ""
Predict the outputmediumData Types

What does this print?

console.log("3" + 4 + 5);
console.log(3 + 4 + "5");
Multiple choicemediumData Types

What does typeof null return?

Fix the bugmediumData Types

The total should be 25, but it prints 1510. Fix the code so the strings are converted to numbers.

const apples = "15";
const pears = "10";
const total = apples + pears;
console.log("Total fruit:", total);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Total fruit: 25"
  • total is a number
Fill in the blankseasyOperators

Add 5 to the score, then check if it's at least 20.

let score = 15;
score  5;
const passed = score  20;
console.log(passed);
Predict the outputeasyOperators

What does this print?

console.log(10 % 3);
console.log(2 + 3 * 4);
Predict the outputmediumOperators

What does this print?

const a = 0 || "default";
const b = 0 ?? "default";
console.log(a, b);
Fix the bugmediumOperators

The program should log Delivery included: true when the cart total is at least 50 and the user is a member. Fix the operators.

const cartTotal = 60;
const isMember = true;
const deliveryIncluded = cartTotal => 50 & isMember;
console.log("Delivery included:", deliveryIncluded);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Delivery included: true"
  • deliveryIncluded is a boolean

7Strings & Template Literals

Read the lesson
Fill in the blankseasyStrings & Template Literals

Build the greeting with a template literal.

const user = "Kai";
const msg = Welcome back, !;
console.log(msg);
Predict the outputeasyStrings & Template Literals

What does this print?

const city = "Paris";
console.log(city.length, city[1]);
Multiple choicemediumStrings & Template Literals

Which kind of quotes makes ${5 * 3} turn into 15?

The message should read Mia has 3 new messages. Fix it using a template literal.

const person = "Mia";
const count = 3;
const message = "${person} has ${count} new messages";
console.log(message);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Mia has 3 new messages"

8String Methods

Read the lesson
Fill in the blankseasyString Methods

Remove the spaces and make it uppercase.

const code = "  abc123  ";
const clean = code.().();
console.log(clean); // "ABC123"
Predict the outputeasyString Methods

What does this print?

console.log("butterfly".slice(0, 6));
Predict the outputmediumString Methods

What does this print?

const tags = "html, css, js".split(", ");
console.log(tags.length, tags[2]);
Fix the bugmediumString Methods

The search should find "Pizza" when the user types "pizza", and the result should log Found: true. Fix it.

const menu = "Burger, Pizza, Salad";
const query = "pizza";
const found = menu.include(query);
console.log("Found:", found);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Found: true"
  • No errors

9Numbers & Math

Read the lesson
Fill in the blankseasyNumbers & Math

Round 7.8 down and 7.2 up.

console.log(Math.(7.8)); // 7
console.log(Math.(7.2));  // 8
Predict the outputeasyNumbers & Math

What does this print?

console.log(Math.round(3.5), Math.max(4, 11, 7));
Multiple choicemediumNumbers & Math

Which expression gives a random whole number from 1 to 10?

Fix the bugmediumNumbers & Math

The average should be 82.5 and display as Average: 82.50. Fix the bugs.

const scores = ["80", "85"];
const sum = scores[0] + scores[1];
const average = sum / scores.length;
console.log("Average:", average.toFixed(2));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Average: 82.50"

10Booleans & Comparisons

Read the lesson
Fill in the blankseasyBooleans & Comparisons

Use strict comparisons.

const pin = 1234;
console.log(pin  1234); // true
console.log(pin  1111); // true
Predict the outputmediumBooleans & Comparisons

What does this print?

console.log(Boolean("0"), Boolean(0), Boolean([]));
Multiple choicemediumBooleans & Comparisons

Which of these is falsy?

Fix the bugmediumBooleans & Comparisons

The check should log Access: true only when the code typed is exactly the number 42. The input arrives as a string. Fix it so it uses strict equality correctly.

const typed = "42";
const access = typed = 42;
console.log("Access:", access);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Access: true"
  • access is a boolean
  • No errors

11Logical Operators

Read the lesson
Fill in the blankseasyLogical Operators

Give size a default of 12 only if fontSize is null or undefined.

const fontSize = null;
const size = fontSize  12;
console.log(size);
Predict the outputmediumLogical Operators

What is logged?

console.log(0 || "a", 0 ?? "b", "" && "c");
Multiple choiceeasyLogical Operators

Which condition is true only when both values are true?

Multiple choicemediumLogical Operators

What does user.settings?.theme return if settings is undefined?

Fix the bugmediumLogical Operators

describe should return "no charge" for children under 5 or adults over 65, keep a discount of 0, and not crash when pass is missing. Fix the three bugs.

function describe(age, pass) {
  const discount = pass.discount || 10;
  const exempt = age < 5 && age > 65;
  return exempt ? "no charge" : `pay, discount ${discount}`;
}
console.log(describe(3));
console.log(describe(30, { discount: 0 }));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Young children pay nothing
  • Over 65s pay nothing
  • A discount of 0 is kept
  • No pass gives the default

12if / else

Read the lesson
Fill in the blankseasyif / else

Complete the condition.

const age = 20;
 (age >= 18) {
  console.log("Adult");
}  {
  console.log("Minor");
}
Predict the outputmediumif / else

What does this print?

const x = 12;
if (x > 5) {
  console.log("A");
} else if (x > 10) {
  console.log("B");
} else {
  console.log("C");
}
Multiple choicemediumif / else

Which condition is true on Saturday or Sunday?

Fix the bugmediumif / else

The program should print Delivery included! when the basket is £40 or more, otherwise Add £X to get delivery included. It currently has two bugs. Fix them.

const basket = 32;

if (basket > 40); {
  console.log("Delivery included!");
} else {
  console.log(`Add £${40 - basket} to get delivery included`);
}
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Add £8 to get delivery included"
  • Does not log the included message
  • No errors
Fill in the blankseasyswitch

Complete the switch.

switch (pet) {
   "dog":
    console.log("Woof");
    ;
  :
    console.log("...");
}
Predict the outputmediumswitch

What does this print?

const x = "2";
switch (x) {
  case 2:
    console.log("number");
    break;
  default:
    console.log("no match");
}
Multiple choicemediumswitch

What happens if a matching case has no break?

Fix the bugmediumswitch

Picking "M" should log Price: 7, but it logs Price: 9. Fix it.

const size = "M";
let price;

switch (size) {
  case "S":
    price = 5;
  case "M":
    price = 7;
  case "L":
    price = 9;
}

console.log("Price:", price);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Price: 7"

14for Loops

Read the lesson
Fill in the blankseasyfor Loops

Log the numbers 1 to 3.

for (let i = 1; i  3; ) {
  console.log(i);
}
Predict the outputeasyfor Loops

What does this print?

for (let i = 0; i < 3; i++) {
  console.log(i * 2);
}
Predict the outputmediumfor Loops

How many times does "Hi" print?

for (let i = 10; i > 0; i -= 2) {
  console.log("Hi");
}
Fix the bugmediumfor Loops

This should log every guest's name in capitals, but it logs undefined at the end and crashes. Fix the loop.

const guests = ["ana", "ben", "cleo"];

for (let i = 0; i <= guests.length; i++) {
  console.log(guests[i].toUpperCase());
}
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs the three names in capitals
  • No errors

15while Loops

Read the lesson
Fill in the blankseasywhile Loops

Count down from 3 to 1.

let n = 3;
 (n > 0) {
  console.log(n);
  n;
}
Predict the outputmediumwhile Loops

What does this print?

let x = 10;
while (x < 5) {
  console.log("inside");
}
console.log("done");
Multiple choicemediumwhile Loops

Which loop always runs its body at least once?

Fix the bugmediumwhile Loops

This loop should halve the number until it's below 1 and log Steps: 7, but it never ends. Fix it.

let value = 100;
let steps = 0;

while (value >= 1) {
  steps++;
}

console.log("Steps:", steps);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Steps: 7"
  • No errors

16for...of & break

Read the lesson
Fill in the blankseasyfor...of & break

Loop over each colour's value.

const colours = ["red", "green", "blue"];
for (const colour  colours) {
  console.log(colour);
}
Predict the outputmediumfor...of & break

What is logged?

for (const n of [1, 2, 3, 4, 5]) {
  if (n === 2) continue;
  if (n === 4) break;
  console.log(n);
}
Multiple choiceeasyfor...of & break

What does for...in give you for an object?

Multiple choicemediumfor...of & break

Which loop can you stop early with break?

Fix the bugmediumfor...of & break

firstNegative should return the first negative number in the array, or null if there isn't one. Fix it.

function firstNegative(nums) {
  let found = null;
  for (const i in nums) {
    if (nums[i] < 0) {
      found = i;
      continue;
    }
  }
  return found;
}
console.log(firstNegative([4, -2, 7, -9]));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Returns the first negative value
  • Returns null when there is none
  • Works when the first item is negative

17Functions

Read the lesson
Fill in the blankseasyFunctions

Complete the function so it returns the area of a rectangle.

 area(width, height) {
   width * height;
}
console.log(area(3, 4)); // 12
Predict the outputeasyFunctions

What does this print?

function add(a, b = 10) {
  return a + b;
}
console.log(add(5), add(5, 1));
Predict the outputmediumFunctions

What does this print?

function shout(word) {
  console.log(word.toUpperCase());
}
const result = shout("hey");
console.log(result);
Fix the bugmediumFunctions

getInitials("Grace Hopper") should return "GH". Fix the function.

function getInitials(fullName) {
  const parts = fullName.split(" ");
  const initials = parts[0][0] + parts[1][0];
  console.log(initials);
}

console.log(getInitials("Grace Hopper"));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • getInitials returns "GH"
  • Works for another name

18Arrow Functions

Read the lesson
Fill in the blankseasyArrow Functions

Turn this into a one-line arrow function with an implicit return.

const triple =   n * 3;
console.log(triple(4)); // 12
Predict the outputmediumArrow Functions

What does this print?

const greet = name => `Hi ${name}`;
const nothing = () => {};
console.log(greet("Lu"), nothing());
Multiple choicemediumArrow Functions

How do you return an object from an arrow function in one line?

Fix the bugmediumArrow Functions

isEven should return true/false and squareAll should return the squared array. Fix both arrows.

const isEven = (n) => { n % 2 === 0 };
const squareAll = (arr) => arr.map((x) => { x * x });

console.log(isEven(4), squareAll([1, 2, 3]));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • isEven(4) is true
  • isEven(7) is false
  • squareAll([1, 2, 3]) is [1, 4, 9]

19Scope & Closures

Read the lesson
Multiple choiceeasyScope & Closures

Where can a const declared inside an if block be used?

Predict the outputmediumScope & Closures

What does this print?

let x = "outer";
function test() {
  let x = "inner";
  console.log(x);
}
test();
console.log(x);
Predict the outputhardScope & Closures

What does this print?

function make() {
  let n = 0;
  return () => n += 10;
}
const add = make();
add();
console.log(add());
Fix the bugmediumScope & Closures

message is used outside the block it was declared in. Fix the code so it logs Status: Open without errors.

const hour = 10;

if (hour >= 9 && hour < 17) {
  const message = "Open";
} else {
  const message = "Closed";
}

console.log("Status:", message);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Status: Open"
  • No errors

20Hoisting & var vs let

Read the lesson
Fill in the blankseasyHoisting & var vs let

Declare a value that will never be reassigned.

 TAX_RATE = 0.2;
console.log(TAX_RATE);
Predict the outputmediumHoisting & var vs let

What is logged?

console.log(typeof x, typeof y);
var x = 1;
function y() {}
Multiple choiceeasyHoisting & var vs let

What scope does let have?

Multiple choicemediumHoisting & var vs let

What is the temporal dead zone?

Fix the bugmediumHoisting & var vs let

makeHandlers should return three functions that return 0, 1 and 2, and total should not leak into the global scope. Fix it.

function makeHandlers() {
  const list = [];
  for (var i = 0; i < 3; i++) list.push(() => i);
  return list;
}
function addUp(nums) {
  total = 0;
  for (const n of nums) total += n;
  return total;
}
console.log(makeHandlers().map(f => f()), addUp([1, 2]));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Each handler keeps its own value
  • addUp still works
  • total is not a global

21Callbacks

Read the lesson
Fill in the blankseasyCallbacks

Pass logItem as the callback to forEach without calling it.

function logItem(item) { console.log(item); }
["a", "b"].forEach();
Predict the outputmediumCallbacks

What is logged?

function make(x) {
  return (y) => x + y;
}
const add5 = make(5);
console.log(add5(2), make(1)(1));
Multiple choiceeasyCallbacks

What is a callback?

Multiple choicemediumCallbacks

What is a closure?

Fix the bugmediumCallbacks

applyToAll should return a new array with fn applied to every item, and addTax should be a function returned by withTax that adds 20%. Fix both.

function applyToAll(items, fn) {
  const out = [];
  for (const item of items) out.push(fn);
  return out;
}
function withTax(rate) {
  (price) => price * (1 + rate);
}
const addTax = withTax(0.2);
console.log(applyToAll([10, 20], addTax));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • withTax returns a function
  • Tax is added
  • applyToAll calls the callback for each item

22Recursion

Read the lesson
Fill in the blankseasyRecursion

Complete the base case so power(2, 0) returns 1.

function power(base, exp) {
  if (exp === ) return 1;
  return base * power(base, exp - 1);
}
console.log(power(2, 5));
Predict the outputmediumRecursion

What does this log?

function f(n) {
  if (n === 0) return "";
  return n + f(n - 1);
}
console.log(f(3));
Multiple choiceeasyRecursion

What stops a recursive function from running forever?

Multiple choicemediumRecursion

Which error appears when recursion goes too deep?

Fix the bugmediumRecursion

depth(obj) should return how deeply objects are nested: {} is 1, { a: {} } is 2. Non-object values count as 0. Fix the function.

function depth(value) {
  if (typeof value === "object") return 0;
  let deepest = 0;
  for (const key in value) {
    deepest = Math.max(deepest, depth(value));
  }
  return deepest;
}
console.log(depth({ a: { b: {} } }));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Empty object is 1
  • Nested objects count each level
  • Plain values are 0
  • Takes the deepest branch
Fill in the blankseasyArrays

Add "kiwi" to the end and remove the first item.

const fruit = ["apple", "pear"];
fruit.("kiwi");
fruit.();
console.log(fruit); // ["pear", "kiwi"]
Predict the outputeasyArrays

What does this print?

const nums = [5, 10, 15];
console.log(nums.length, nums[nums.length - 1]);
Predict the outputmediumArrays

What does this print?

const a = ["x"];
const b = a;
b.push("y");
console.log(a.length);
Fix the bugmediumArrays

The code should remove "Tuesday" from the list and log Mon, Wed, Thu. Fix it.

const days = ["Mon", "Tue", "Wed", "Thu"];
const pos = days.indexOf("Tuesday");
days.splice(pos);
console.log(days.join(", "));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Mon, Wed, Thu"

24Array Methods (map, filter…)

Read the lesson
Fill in the blankseasyArray Methods (map, filter…)

Double every number, then keep only those over 5.

const result = [1, 2, 3, 4]
  .(n => n * 2)
  .(n => n > 5);
console.log(result); // [6, 8]
Predict the outputmediumArray Methods (map, filter…)

What does this print?

const r = [3, 5, 7].reduce((sum, n) => sum + n, 10);
console.log(r);
Multiple choicemediumArray Methods (map, filter…)

Which method returns the first matching item (not an array)?

Predict the outputmediumArray Methods (map, filter…)

What does this print?

const ages = [12, 19, 25];
console.log(ages.some(a => a < 13), ages.every(a => a > 18));

The code should log the names of users over 18 in alphabetical order: ["Ana", "Zoe"]. Fix it.

const users = [
  { name: "Zoe", age: 22 },
  { name: "Max", age: 16 },
  { name: "Ana", age: 30 },
];

const adults = users.forEach(u => u.age > 18);
const names = adults.map(u => { u.name });
console.log(names.sort());
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs ["Ana", "Zoe"]
  • No errors

25Sort & Search Arrays

Read the lesson
Fill in the blankseasySort & Search Arrays

Sort the numbers from smallest to largest.

const nums = [30, 4, 15];
nums.sort((a, b) => a  b);
console.log(nums);
Predict the outputmediumSort & Search Arrays

What is logged?

const a = [3, 1, 2];
const b = a.toSorted();
a.reverse();
console.log(a.join(""), b.join(""));
Multiple choiceeasySort & Search Arrays

Which method returns the first object that matches a condition?

Multiple choicemediumSort & Search Arrays

Which compare function sorts names alphabetically, handling accents?

Fix the bugmediumSort & Search Arrays

topThree(players) should return the names of the three highest scorers, highest first, without changing the original array. Fix it.

function topThree(players) {
  return players.sort((a, b) => a.score > b.score).slice(0, 3).map(p => p.name);
}
const players = [
  { name: "A", score: 5 }, { name: "B", score: 50 }, { name: "C", score: 12 }, { name: "D", score: 30 },
];
console.log(topThree(players), players[0].name);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Returns the top three, highest first
  • Original order is kept
Fill in the blankseasyObjects

Read the city with dot notation, and the country using the variable key.

const place = { city: "Lagos", country: "Nigeria" };
const key = "country";
console.log(place.);
console.log(place[  ]);
Predict the outputeasyObjects

What does this print?

const car = { brand: "Tesla", year: 2022 };
car.year = 2024;
console.log(car.year, car.color);
Multiple choicemediumObjects

Which line safely reads user.profile.avatar when profile might not exist?

Fix the bugmediumObjects

The code should log Mia: 3 pets but crashes and prints the wrong thing. Fix it.

const owner = {
  name: "Mia",
  pets: ["cat", "rabbit", "fish"],
  describe: () => {
    return `${this.name}: ${this.pets.lenght} pets`;
  },
};

console.log(owner.describe());
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Mia: 3 pets"
  • No errors

27Object Methods

Read the lesson
Fill in the blankseasyObject Methods

Get an array of the object's keys.

const car = { make: "Mini", year: 2020 };
console.log(Object.(car));
Predict the outputmediumObject Methods

What is logged?

const a = { list: [1] };
const b = { ...a };
b.list.push(2);
console.log(a.list.length, a === b);
Multiple choiceeasyObject Methods

Which makes a deep copy of nested data?

Multiple choicemediumObject Methods

What does a getter do?

Fix the bugmediumObject Methods

withDiscount(product, percent) should return a new product with a lower price, leaving the original and its nested tags array unchanged. Also, product.label should be a getter. Fix it.

const product = {
  name: "Lamp",
  price: 40,
  tags: ["home"],
  label() { return `${this.name} £${this.price}`; },
};
function withDiscount(item, percent) {
  const copy = item;
  copy.price = item.price * (1 - percent / 100);
  copy.tags.push("sale");
  return copy;
}
const sale = withDiscount(product, 25);
console.log(sale.price, product.price, product.tags);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Discounted copy
  • Original price unchanged
  • Original tags unchanged
  • label is a getter

28this & bind()

Read the lesson
Fill in the blankseasythis & bind()

Create a version of show with this fixed to item.

const item = { name: "Lamp" };
function show() { return this.name; }
const showItem = show.(item);
console.log(showItem());
Predict the outputmediumthis & bind()

What is logged?

const a = { n: 1, get() { return this.n; } };
const b = { n: 2 };
b.get = a.get;
console.log(a.get(), b.get());
Multiple choiceeasythis & bind()

In user.save(), what is this inside save?

Multiple choicemediumthis & bind()

What's the difference between call and bind?

Fix the bugmediumthis & bind()

stopwatch.start() should increase seconds by 1 every 50ms, and getLabel (a copy of the method) should still return the right label. Fix the this problems.

const stopwatch = {
  seconds: 0,
  label() { return `${this.seconds}s`; },
  start() {
    this.id = setInterval(function () {
      this.seconds++;
    }, 50);
  },
};
stopwatch.start();
const getLabel = stopwatch.label;
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Seconds increase
  • The copied method keeps this

29Destructuring & Spread

Read the lesson
Fill in the blankseasyDestructuring & Spread

Pull out name and price, and combine the two arrays.

const product = { name: "Mug", price: 8 };
const { ,  } = product;
const all = [ a, b ];
Predict the outputmediumDestructuring & Spread

What does this print?

const [a, , c = 9, d = 4] = [1, 2, 3];
console.log(a, c, d);
Predict the outputmediumDestructuring & Spread

What does this print?

const base = { size: "M", color: "red" };
const order = { ...base, color: "blue", qty: 2 };
console.log(order.color, base.color);
Fix the bugmediumDestructuring & Spread

average(…) should accept any number of arguments and return their average. average(2, 4, 6) should be 4. Fix the function.

function average(nums) {
  const total = nums.reduce((s, n) => s + n, 0);
  return total / nums.length;
}

console.log(average(2, 4, 6));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • average(2, 4, 6) is 4
  • average(10) is 10

30Sets & Maps

Read the lesson
Fill in the blankseasySets & Maps

Remove the duplicates from the array.

const ids = [4, 4, 7, 2, 7];
const unique = [...new (ids)];
console.log(unique);
Predict the outputmediumSets & Maps

What is logged?

const s = new Set("banana");
console.log(s.size, [...s].join(""));
Multiple choiceeasySets & Maps

Which method reads a value from a Map?

Multiple choicemediumSets & Maps

When is a Map a better choice than an object?

Fix the bugmediumSets & Maps

tally(items) should return a Map of each item to how many times it appears. Fix the bugs.

function tally(items) {
  const counts = new Map();
  for (const item of items) {
    counts[item] = counts.get(item) + 1;
  }
  return counts;
}
const t = tally(["a", "b", "a"]);
console.log(t.get("a"), t.size);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Counts repeats
  • Counts single items
  • Size is the number of different items

31Dates & Intl

Read the lesson
Fill in the blankseasyDates & Intl

Get the four-digit year from a date.

const d = new Date("2026-05-20");
console.log(d.());
Predict the outputmediumDates & Intl

What is logged?

const d = new Date(2026, 0, 31);
d.setDate(d.getDate() + 1);
console.log(d.getMonth(), d.getDate());
Multiple choiceeasyDates & Intl

What does getDay() return for a Sunday?

Multiple choicemediumDates & Intl

Which formats 9.5 as "$9.50"?

Fix the bugmediumDates & Intl

daysBetween(a, b) should return the whole number of days from date a to date b, and christmas(year) should return 25 December of that year. Fix both.

function daysBetween(a, b) {
  return (b - a) / 1000;
}
function christmas(year) {
  return new Date(year, 12, 25);
}
console.log(daysBetween(new Date(2026, 0, 1), new Date(2026, 0, 11)));
console.log(christmas(2026).toDateString());
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Ten days apart
  • Christmas is in December
  • Same year

32Regular Expressions

Read the lesson
Fill in the blankseasyRegular Expressions

Make the pattern match one or more digits.

const hasNumber = /\d/;
console.log(hasNumber.test("Room 101"));
Predict the outputmediumRegular Expressions

What is logged?

console.log("cat Cat CAT".match(/cat/gi).length, /^cat$/.test("cats"));
Multiple choiceeasyRegular Expressions

Which method returns true or false?

Multiple choicemediumRegular Expressions

What does [^0-9] match?

Fix the bugmediumRegular Expressions

isValidCode should accept exactly two capital letters followed by exactly three digits, like "AB123". tidy should replace every run of spaces with a single space. Fix both patterns.

function isValidCode(code) {
  return /[A-Z]{2}\d{3}/.test(code);
}
function tidy(text) {
  return text.replace(/ +/, " ");
}
console.log(isValidCode("AB123"), isValidCode("xAB1234"), tidy("a   b   c"));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Accepts a valid code
  • Rejects extra characters
  • Tidies every gap

33DOM: Selecting Elements

Read the lesson
Fill in the blankseasyDOM: Selecting Elements

Select the first .card and all .card elements.

const one = document.(".card");
const all = document.(".card");
Multiple choiceeasyDOM: Selecting Elements

What does document.querySelector(".missing") return when nothing matches?

Multiple choicemediumDOM: Selecting Elements

You're inside a click handler with the clicked button. How do you get the .product that contains it?

Fix the bugmediumDOM: Selecting Elements

The code should log the number of .task items (3) and the text of the item with id urgent. Fix the selectors.

const tasks = document.querySelector("task");
const urgent = document.getElementById("#urgent");

console.log(tasks.length);
console.log(urgent.textContent);
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs 3
  • Logs "Pay rent"
  • No errors

34DOM: Changing Elements

Read the lesson
Fill in the blankseasyDOM: Changing Elements

Change the text safely and turn on the open class.

const menu = document.querySelector(".menu");
menu. = "Menu (open)";
menu.classList.("open");
Multiple choicemediumDOM: Changing Elements

Which is safe to use with text a user typed?

Multiple choicemediumDOM: Changing Elements

What does el.classList.toggle("dark") do?

Fix the bugmediumDOM: Changing Elements

The code should add three <li> items to the list and make the title red. Fix the mistakes.

const colors = ["Red", "Green", "Blue"];
const list = document.querySelector("#colors");

colors.forEach(c => {
  const li = document.createElement("<li>");
  li.textContent = c;
  list.append;
});

document.querySelector("#title").style.colour = "red";
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Three list items exist
  • Items have the right text
  • Title is red
  • No errors

35Create & Remove Elements

Read the lesson
Fill in the blankseasyCreate & Remove Elements

Create a paragraph element and add it to the body.

const p = document.("p");
p.textContent = "Hello";
document.body.(p);
Predict the outputmediumCreate & Remove Elements

What is logged?

const ul = document.createElement("ul");
const a = document.createElement("li");
const b = document.createElement("li");
ul.append(a, b);
ul.prepend(b);
console.log(ul.children.length, ul.firstElementChild === b);
Multiple choiceeasyCreate & Remove Elements

Which removes an element from the page?

Multiple choicemediumCreate & Remove Elements

Why use textContent instead of innerHTML for user data?

Fix the bugmediumCreate & Remove Elements

addRow(name) should add a new <li> with the name as text to the end of #people, and each row's button should remove only its own row. Fix it.

function addRow(name) {
  const li = document.createElement("li");
  li.innerHTML = name + ' <button>x</button>';
  document.querySelector("#people").prepend(li);
  li.querySelector("button").addEventListener("click", () => {
    document.querySelector("#people").remove();
  });
}
addRow("Ana");
addRow("<b>Ben</b>");
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Rows are added at the end
  • Names are text, not HTML
  • A button removes only its row
Fill in the blankseasyEvents

Run toggleMenu when the button is clicked.

menuButton.("", toggleMenu);
Multiple choicemediumEvents

What does event.preventDefault() do in a submit handler?

Multiple choicemediumEvents

Which event fires on every keystroke in a text box?

Fix the bugmediumEvents

Clicking the button should toggle the dark class on the box and log Dark: true the first time. Fix the bugs.

const box = document.querySelector("#box");
const toggle = document.querySelector("#toggle");

toggle.addEventListener("onclick", () => {
  box.classList.toggle("dark");
  console.log("Dark:", box.classList.contains("dark"));
});
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Clicking toggles the dark class
  • Logs "Dark: true" after a click

37Event Delegation

Read the lesson
Fill in the blankseasyEvent Delegation

Find the list item that was clicked, even if the click landed on something inside it.

list.addEventListener("click", (event) => {
  const item = event.target.("li");
  console.log(item?.textContent);
});
Predict the outputmediumEvent Delegation

A list ul has a click listener, and you click a <b> inside one of its <li> elements. What are e.target.tagName and e.currentTarget.tagName?

ul.addEventListener("click", (e) => console.log(e.target.tagName, e.currentTarget.tagName));
Multiple choiceeasyEvent Delegation

What is event bubbling?

Multiple choicemediumEvent Delegation

What's the main advantage of event delegation?

Fix the bugmediumEvent Delegation

Clicking any Remove button, including on rows added later, should remove its own row. Fix it with delegation.

document.querySelectorAll(".rm").forEach((btn) => {
  btn.addEventListener("click", (e) => e.currentTarget.parentElement.parentElement.remove());
});
const extra = document.createElement("li");
extra.innerHTML = 'Row 2 <button class="rm">Remove</button>';
document.querySelector("#rows").append(extra);
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • The added row's button works
  • The list itself survives

38Forms & Validation

Read the lesson
Fill in the blankseasyForms & Validation

Stop the form from reloading the page.

form.addEventListener("submit", (event) => {
  event.();
  console.log("Handled with JavaScript");
});
Predict the outputmediumForms & Validation

An input has value="5". What is logged?

console.log(qty.value + 2, qty.valueAsNumber + 2);
Multiple choiceeasyForms & Validation

Which property tells you if a checkbox is ticked?

Multiple choicemediumForms & Validation

What does input.setCustomValidity("") do?

Fix the bugmediumForms & Validation

On submit, the form should not reload, and #out should show the email and whether "terms" is ticked, like ana@example.com true. Fix it.

const form = document.querySelector("#f");
document.querySelector("#go").addEventListener("click", () => {
  const data = new FormData(form);
  document.querySelector("#out").textContent = `${data.email} ${form.elements.terms.value}`;
});
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Shows the email and ticked state
  • Listens for submit

39Timers (setTimeout)

Read the lesson
Fill in the blankseasyTimers (setTimeout)

Log "Hi" once after 2 seconds.

(() => console.log("Hi"), );
Predict the outputmediumTimers (setTimeout)

In what order are the letters logged?

setTimeout(() => console.log("A"), 0);
console.log("B");
setTimeout(() => console.log("C"), 0);
console.log("D");
Multiple choicemediumTimers (setTimeout)

How do you stop an interval?

Fix the bugmediumTimers (setTimeout)

This should log tick exactly 3 times and then done, but it never stops. Fix it.

let count = 0;

setInterval(() => {
  count++;
  console.log("tick");
  if (count === 3) {
    console.log("done");
  }
}, 100);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Ticks exactly 3 times then done

40Debounce & Throttle

Read the lesson
Fill in the blankseasyDebounce & Throttle

Cancel the previous timer so only the last call runs.

let timer;
function onType(text) {
  (timer);
  timer = setTimeout(() => console.log(text), 300);
}
onType("a"); onType("ab"); onType("abc");
Predict the outputmediumDebounce & Throttle

log is debounced with 100ms. What is logged after a short wait?

const log = debounce((x) => console.log(x), 100);
log(1); log(2); log(3);
setTimeout(() => log(4), 300);
Multiple choiceeasyDebounce & Throttle

Which technique suits a search box that queries a server?

Multiple choicemediumDebounce & Throttle

Which technique suits updating a scroll progress bar?

Fix the bugmediumDebounce & Throttle

debounce(fn, ms) should return a function that waits until it hasn't been called for ms milliseconds, then calls fn once with the latest arguments. Fix it.

function debounce(fn, ms) {
  return (...args) => {
    let timer;
    clearTimeout(timer);
    timer = setTimeout(fn, ms);
  };
}
const calls = [];
const d = debounce((v) => calls.push(v), 50);
d("a"); d("b"); d("c");
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Runs once with the latest value
  • Separate bursts run separately

41localStorage

Read the lesson
Fill in the blankseasylocalStorage

Save and then read the user's name.

localStorage.("username", "Ola");
const name = localStorage.("username");
Multiple choiceeasylocalStorage

What does localStorage.getItem("missing") return?

Multiple choicemediumlocalStorage

How do you store an array in localStorage?

Fix the bugmediumlocalStorage

The high score should be saved as a number and doubled to log Double: 84. Fix the reading code.

localStorage.setItem("high", JSON.stringify(42));

const high = localStorage.getItem("high");
console.log("Double:", high + high);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Double: 84"
Fill in the blankseasyJSON

Turn the object into JSON, then back again.

const text = JSON.({ score: 10 });
const data = JSON.(text);
Multiple choiceeasyJSON

Which is valid JSON?

Predict the outputmediumJSON

What does this print?

console.log(JSON.stringify({ a: 1, b: undefined, c: null }));
Fix the bugmediumJSON

The code should parse the saved settings and log Theme: dark. Fix it.

const saved = "{'theme': 'dark', 'size': 16,}";
const settings = JSON.parse(saved);
console.log("Theme:", settings.theme);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Theme: dark"
  • No errors

43Window & Browser APIs

Read the lesson
Fill in the blankseasyWindow & Browser APIs

Read the id parameter from the URL's query string.

const params = new (location.search);
console.log(params.get("id"));
Predict the outputmediumWindow & Browser APIs

What is logged?

const u = new URL("https://a.com/shop?x=1&x=2#top");
console.log(u.pathname, u.searchParams.get("x"), u.hash);
Multiple choiceeasyWindow & Browser APIs

Which changes the URL without reloading the page?

Multiple choicemediumWindow & Browser APIs

Why use IntersectionObserver instead of a scroll listener?

Fix the bugmediumWindow & Browser APIs

buildSearchUrl(base, term, page) should return a URL string with q and page parameters, correctly encoded. readPage(url) should return the page as a number, defaulting to 1. Fix both.

function buildSearchUrl(base, term, page) {
  return base + "?q=" + term + "&page" + page;
}
function readPage(url) {
  return new URL(url).searchParams.get("page");
}
console.log(buildSearchUrl("https://a.com/search", "tea & cake", 2));
console.log(readPage("https://a.com/search?page=4"));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Builds an encoded URL
  • Reads the page as a number
  • Defaults to page 1

44Responsive JavaScript

Read the lesson
Fill in the blankseasyResponsive JavaScript

Check whether the screen is at least 1024px wide.

const isLarge = window.("(min-width: 1024px)").matches;
console.log(isLarge);
Predict the outputmediumResponsive JavaScript

The window starts at 500px wide and is dragged slowly to 900px. How many times does this log?

matchMedia("(min-width: 768px)").addEventListener("change", () => console.log("changed"));
Multiple choiceeasyResponsive JavaScript

Which query detects that the user prefers less animation?

Multiple choicemediumResponsive JavaScript

Which tool reacts when a sidebar opens and a chart's container gets narrower, without the window changing size?

Fix the bugmediumResponsive JavaScript

watchLayout(callback) should call callback(true) or callback(false) immediately for whether the viewport is at least 700px wide, then again each time that changes. It should return the MediaQueryList. Fix it.

function watchLayout(callback) {
  const mq = window.matchMedia("min-width: 700px");
  window.addEventListener("resize", () => callback(mq.matches));
  return mq;
}
watchLayout((wide) => console.log("wide?", wide));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Uses a valid media query
  • Calls back immediately
  • Listens for change on the query

45Canvas & Animation

Read the lesson
Fill in the blankseasyCanvas & Animation

Get the 2D drawing context.

const ctx = canvas.("2d");
ctx.fillRect(10, 10, 50, 50);
Predict the outputmediumCanvas & Animation

On a canvas, where is the point (0, 100)?

ctx.fillRect(0, 100, 10, 10);
Multiple choiceeasyCanvas & Animation

Which function should drive a smooth animation loop?

Multiple choicemediumCanvas & Animation

Why multiply speed by elapsed time each frame?

Fix the bugmediumCanvas & Animation

drawDots(ctx, points) should clear the whole canvas, then draw a separate filled circle of radius 5 at each point. Fix the three bugs.

function drawDots(ctx, points) {
  ctx.clearRect(0, 0, 10, 10);
  for (const p of points) {
    ctx.arc(p.x, p.y, 5, 0, Math.PI);
    ctx.fill();
  }
}
const ctx = document.querySelector("#c").getContext("2d");
drawDots(ctx, [{ x: 20, y: 20 }, { x: 100, y: 50 }]);
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Draws full circles
  • Clears the whole canvas
  • Circles are separate shapes

46Errors (try/catch)

Read the lesson
Fill in the blankseasyErrors (try/catch)

Catch the error and print its message.

 {
  JSON.parse("{bad json}");
}  (error) {
  console.log(error.message);
}
Multiple choiceeasyErrors (try/catch)

What does ReferenceError: total is not defined usually mean?

Predict the outputmediumErrors (try/catch)

What does this print?

try {
  console.log("A");
  throw new Error("B");
  console.log("C");
} catch (e) {
  console.log(e.message);
} finally {
  console.log("D");
}
Fix the bugmediumErrors (try/catch)

divide(10, 0) should throw an Error with the message Cannot divide by zero, and the code should catch it and log that message. Fix it.

function divide(a, b) {
  if (b === 0) {
    return "Cannot divide by zero";
  }
  return a / b;
}

try {
  divide(10, 0);
} catch (error) {
  console.log(error.message);
}
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • divide(10, 2) is 5
  • divide(1, 0) throws an Error
  • Logs the message

47Debugging

Read the lesson
Fill in the blankseasyDebugging

Show an array of objects as a table in the console.

const people = [{ name: "Ana", age: 31 }, { name: "Ben", age: 27 }];
console.(people);
Predict the outputmediumDebugging

What does this error message tell you?

// TypeError: Cannot read properties of undefined (reading 'length')
console.log(order.items.length);
Multiple choiceeasyDebugging

Which statement pauses code when DevTools is open?

Multiple choicemediumDebugging

Which stepping control runs the current line without entering the functions it calls?

Fix the bugmediumDebugging

average(scores) should return the mean of the numbers, but some scores arrive as strings and one is missing. Convert strings to numbers, skip missing (null or undefined) values, and return 0 for an empty list.

function average(scores) {
  let total = 0;
  for (const s of scores) total += s;
  return total / scores.length;
}
console.log(average([10, "20", null, 30]));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Handles strings and missing values
  • Plain numbers still work
  • Empty list gives 0
Fill in the blankseasyPromises

Handle success and failure.

loadScores()
  .(scores => console.log(scores))
  .(error => console.log("Failed:", error.message));
Predict the outputmediumPromises

In what order are the numbers logged?

console.log(1);
Promise.resolve().then(() => console.log(2));
console.log(3);
Multiple choicemediumPromises

What does Promise.all do if one promise rejects?

Fix the bugmediumPromises

The chain should log Total: 30. A value is being lost. Fix it.

Promise.resolve(10)
  .then(n => {
    n * 3;
  })
  .then(total => console.log("Total:", total));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Total: 30"

49async / await

Read the lesson
Fill in the blankseasyasync / await

Make the function async and wait for the data.

 function start() {
  const data =  loadData();
  console.log(data);
}
Multiple choicemediumasync / await

What does an async function always return?

Predict the outputmediumasync / await

In what order are the letters logged?

async function run() {
  console.log("B");
  await null;
  console.log("D");
}
console.log("A");
run();
console.log("C");
Fix the bugmediumasync / await

getTotal should wait for both prices and log Total: 30. Fix it.

const price = (n) => new Promise(r => setTimeout(() => r(n), 100));

function getTotal() {
  const a = price(10);
  const b = price(20);
  console.log("Total:", a + b);
}

getTotal();
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Total: 30"
  • getTotal is async

50Event Loop

Read the lesson
Fill in the blankseasyEvent Loop

Schedule a microtask.

(() => console.log("microtask"));
console.log("sync");
Predict the outputmediumEvent Loop

What is logged?

setTimeout(() => console.log("t"), 0);
Promise.resolve().then(() => console.log("p"));
console.log("s");
Multiple choiceeasyEvent Loop

How many things can JavaScript's main thread do at once?

Multiple choicemediumEvent Loop

Which of these is a microtask?

Fix the bugmediumEvent Loop

order() should resolve with the array ["sync", "micro", "task"], recording in the order things actually run. The pushes are in the wrong kinds of callbacks. Fix it without changing the final array.

function order() {
  const log = [];
  return new Promise((resolve) => {
    Promise.resolve().then(() => log.push("task"));
    setTimeout(() => {
      log.push("micro");
      resolve(log);
    }, 0);
    log.push("sync");
  });
}
order().then((log) => console.log(log));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Records the real order

51Fetch API

Read the lesson
Fill in the blankseasyFetch API

Read the JSON body.

const res = await (url);
const data = await res.();
Multiple choicemediumFetch API

What does fetch do when the server replies with 404?

Multiple choicemediumFetch API

Which option sends JSON data to a server?

Fix the bughardFetch API

getTitle(1) should return the title of todo 1 ("delectus aut autem") and log it. Fix the function.

async function getTitle(id) {
  const res = fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
  const todo = res.json();
  return todo.title;
}

getTitle(1).then(t => console.log(t));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • getTitle(1) returns the title
Fill in the blankseasyClasses

Complete the class.

class Book {
  (title) {
    .title = title;
  }
}
const b =  Book("Dune");
Multiple choicemediumClasses

What does super(name) do inside a child class constructor?

Predict the outputmediumClasses

What does this print?

class Counter {
  #n = 0;
  inc() { this.#n++; return this.#n; }
}
const c = new Counter();
c.inc(); c.inc();
console.log(c.inc(), c.n);
Fix the bugmediumClasses

new Square(4).area should be 16, and Square should extend Shape. Fix it.

class Shape {
  constructor(name) {
    this.name = name;
  }
}

class Square extends Shape {
  constructor(side) {
    this.side = side;
    super("square");
  }
  get area() {
    return side * side;
  }
}

console.log(new Square(4).area);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Area of a 4-sided square is 16
  • Square has the name "square"
  • Square is a Shape

53Prototypes

Read the lesson
Fill in the blankseasyPrototypes

Create cat with animal as its prototype.

const animal = { eats: true };
const cat = Object.(animal);
console.log(cat.eats);
Predict the outputmediumPrototypes

What is logged?

const base = { colour: "red" };
const item = Object.create(base);
item.colour = "blue";
console.log(item.colour, base.colour, Object.keys(item).length);
Multiple choiceeasyPrototypes

Where do array methods like map come from?

Multiple choicemediumPrototypes

What does new do first when calling a constructor function?

Fix the bugmediumPrototypes

Every Robot should share one greet method from the prototype, and greet should use the robot's own name. Fix it.

function Robot(name) {
  this.name = name;
}
Robot.greet = () => `Beep, I am ${this.name}`;
const r1 = new Robot("R1");
const r2 = new Robot("R2");
console.log(r1.greet?.());
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Robots can greet
  • The method is shared
  • The method lives on the prototype

54Iterators & Generators

Read the lesson
Fill in the blankseasyIterators & Generators

Hand out each value from the generator.

function* colours() {
   "red";
   "green";
}
console.log([...colours()]);
Predict the outputmediumIterators & Generators

What is logged?

function* g() { yield 1; yield 2; return 3; }
const it = g();
console.log(it.next().value, [...it].length);
Multiple choiceeasyIterators & Generators

What does an iterator's next() return?

Multiple choicemediumIterators & Generators

Which key makes an object work with for...of?

Fix the bugmediumIterators & Generators

range(start, end) should be a generator that yields every whole number from start to end inclusive, so [...range(2, 5)] is [2, 3, 4, 5]. Fix it.

function range(start, end) {
  for (let i = start; i < end; i++) {
    return i;
  }
}
console.log([...range(2, 5)]);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Yields an inclusive range
  • Single value range
  • Is a generator

55Modules (import/export)

Read the lesson
Fill in the blankseasyModules (import/export)

Export a function and import it in another file.

// greet.js
 function hello(name) { return `Hello ${name}`; }

// main.js
 { hello }  "./greet.js";
Multiple choicemediumModules (import/export)

How many default exports can a module have?

Multiple choicemediumModules (import/export)

Which script tag lets you use import?

Fix the bugmediumModules (import/export)

The module should import double (a named export) and log Double: 42. Fix the import.

<script type="module">
  import double from "data:text/javascript,export const double = n => n * 2;";
  console.log("Double:", double(21));
</script>
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Logs "Double: 42"
  • Uses a named import

56Web Workers

Read the lesson
Fill in the blankseasyWeb Workers

Send data to the worker.

const worker = new Worker("worker.js");
worker.({ task: "sort", items: [3, 1, 2] });
Predict the outputmediumWeb Workers

What happens to the original array after this runs?

const list = [1, 2, 3];
worker.postMessage(list);
list.push(4);
// inside the worker: console.log(e.data.length)
Multiple choiceeasyWeb Workers

What is the main reason to use a Web Worker?

Multiple choicemediumWeb Workers

Which of these can a worker use?

Fix the bugmediumWeb Workers

fetchWithTimeout(promiseFactory, ms) should call promiseFactory(signal) with an AbortController signal, and abort it if it takes longer than ms. It should resolve with the result when fast enough. Fix it.

function fetchWithTimeout(promiseFactory, ms) {
  const controller = new AbortController();
  setTimeout(() => controller.abort, ms);
  return promiseFactory();
}
const slow = (signal) => new Promise((resolve, reject) => {
  const t = setTimeout(() => resolve("data"), 200);
  signal?.addEventListener("abort", () => { clearTimeout(t); reject(new Error("aborted")); });
});
fetchWithTimeout(slow, 50).then(console.log, (e) => console.log(e.message));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Slow tasks are aborted
  • Fast tasks resolve

Next steps