JavaScript Exercises

Practise what you've learned. Type the missing piece into each highlighted gap and press Check. Further down are coding problems to solve in the editor, each with a worked solution.

Fill in the blanks

Basics

Declare a variable that can never be reassigned.

 maxUsers = 100;

Print a message to the console.

console.("Hello!");

Check the type of a value.

console.log( "hello"); // "string"

Use the operator that compares value AND type.

if (age  18) { console.log("Just turned 18"); }

Use a default of 10 only when size is null or undefined.

const pageSize = size  10;

Complete the ternary.

const label = count === 1  "item" : "items";

Stop the switch case from falling through.

switch (day) {
  case "Sat":
    console.log("Weekend");
    ;
  default:
    console.log("Weekday");
}

Loop over every value in the array.

for (const fruit  fruits) {
  console.log(fruit);
}

Strings and numbers

Insert the variable into the template literal.

const msg = `Hello, !`;

Remove whitespace from both ends.

const clean = input.();

Convert the input string to a number.

const qty = (input.value);

Round down to a whole number.

const whole = Math.(4.9); // 4

Format to exactly two decimal places.

console.log(price.(2));

Functions

Complete the arrow function that doubles a number.

const double = n  n * 2;

Collect any number of arguments into an array.

function sum() {
  return numbers.reduce((a, b) => a + b, 0);
}

Create a bound copy whose this is always user.

const greet = user.greet.(user);

Arrays and objects

Add an item to the end of the array.

cart.("apple");

Create a new array with every price doubled.

const doubled = prices.(p => p * 2);

Keep only the adults.

const adults = people.(p => p.age >= 18);

Add up all the numbers.

const total = numbers.((sum, n) => sum + n, 0);

Sort numbers in ascending order.

scores.sort((a, b) => );

Pull name and age out of the object.

const {  } = user;

Merge two objects into a new one.

const settings = { ...defaults,  };

Get all of an object's values as an array.

const values = Object.(scores);

Turn an object into a JSON string.

const text = JSON.(data);

Classes, DOM and async

Call the parent class constructor.

class Dog extends Animal {
  constructor(name) {
    (name);
  }
}

Select the first element with the class "card".

const card = document.(".card");

Run a function when the button is clicked.

button.("click", handleClick);

Stop the form from reloading the page.

form.addEventListener("submit", event => {
  event.();
});

Wait for the promise inside an async function.

const response =  fetch(url);

Wait for several promises at the same time.

const [user, posts] = await Promise.([loadUser(), loadPosts()]);

Coding problems

1. Reverse words

Write reverseWords(sentence) that reverses the order of the words: "one two three" → "three two one".

Try it yourself
Console output
Show solution
JS solution.js
function reverseWords(sentence) {
  return sentence.trim().split(/\s+/).reverse().join(" ");
}

console.log(reverseWords("one two three"));
Output
three two one

2. Count vowels

Write countVowels(text) that returns how many vowels (a, e, i, o, u, either case) the text contains.

Try it yourself
Console output
Show solution
JS solution.js
function countVowels(text) {
  return (text.match(/[aeiou]/gi) ?? []).length;
}

console.log(countVowels("JavaScript Is Fun"));
Output
5

A loop with "aeiou".includes(ch.toLowerCase()) works just as well.

3. Group by first letter

Given an array of names, return an object mapping each first letter to the names that start with it.

Try it yourself
Console output
Show solution
JS solution.js
const names = ["Ana", "Ben", "Alex", "Bea", "Cy"];

function groupByLetter(list) {
  const groups = {};
  for (const name of list) {
    const letter = name[0].toUpperCase();
    (groups[letter] ??= []).push(name);
  }
  return groups;
}

console.log(groupByLetter(names));
Output
{ A: [ 'Ana', 'Alex' ], B: [ 'Ben', 'Bea' ], C: [ 'Cy' ] }

Or in one line with Object.groupBy(list, n => n[0].toUpperCase()).

4. Shopping cart total

Calculate the total of a cart, applying a 10% discount when the total before discount is over $100. Return the result rounded to two decimals.

Try it yourself
Console output
Show solution
JS solution.js
const cart = [
  { name: "Shoes", price: 60, qty: 1 },
  { name: "Socks", price: 5, qty: 4 },
  { name: "Hat", price: 25, qty: 1 },
];

function cartTotal(items) {
  const subtotal = items.reduce((sum, i) => sum + i.price * i.qty, 0);
  const total = subtotal > 100 ? subtotal * 0.9 : subtotal;
  return Math.round(total * 100) / 100;
}

console.log(cartTotal(cart));
Output
94.5

5. Make a counter with a closure

Write createCounter(start) that returns an object with increment, decrement and value methods, keeping the count private.

Try it yourself
Console output
Show solution
JS solution.js
function createCounter(start = 0) {
  let count = start;
  return {
    increment: () => ++count,
    decrement: () => --count,
    value: () => count,
  };
}

const c = createCounter(5);
c.increment();
c.increment();
c.decrement();
console.log(c.value(), c.count);
Output
6 undefined

6. Retry with async/await

Write retry(fn, attempts) that calls the async function fn, retrying when it throws, up to attempts times. If every attempt fails, rethrow the last error.

Try it yourself
Console output
Show solution
JS solution.js
let calls = 0;
async function flaky() {
  calls++;
  if (calls < 3) throw new Error(`failed on call ${calls}`);
  return "success!";
}

async function retry(fn, attempts) {
  let lastError;
  for (let i = 1; i <= attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      lastError = err;
      console.log(`attempt ${i} failed`);
    }
  }
  throw lastError;
}

retry(flaky, 5).then(console.log, err => console.log("gave up:", err.message));
Output
attempt 1 failed
attempt 2 failed
success!

Note the return await: without await, a rejection would escape the try/catch.