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;
Use const by default; let only when the value must change (lesson 05).
Print a message to the console.
console.("Hello!");
console.log prints values for debugging (lesson 03).
Check the type of a value.
console.log( "hello"); // "string"
typeof returns the type as a string (lesson 06).
Use the operator that compares value AND type.
if (age 18) { console.log("Just turned 18"); }
Always prefer strict equality === (lesson 08).
Use a default of 10 only when size is null or undefined.
const pageSize = size 10;
?? keeps 0 and "" but replaces null/undefined (lesson 08).
Complete the ternary.
const label = count === 1 "item" : "items";
condition ? a : b (lesson 09).
Stop the switch case from falling through.
switch (day) {
case "Sat":
console.log("Weekend");
;
default:
console.log("Weekday");
}
Without break, execution continues into the next case (lesson 10).
Loop over every value in the array.
for (const fruit fruits) {
console.log(fruit);
}
for…of gives values; for…in gives keys (lesson 12).
Strings and numbers
Insert the variable into the template literal.
const msg = `Hello, !`;
Template literals use ${expression} (lesson 15).
Remove whitespace from both ends.
const clean = input.();
trim() returns a copy without surrounding whitespace (lesson 14).
Convert the input string to a number.
const qty = (input.value);
Number() converts strictly; invalid text gives NaN (lesson 18).
Round down to a whole number.
const whole = Math.(4.9); // 4
Math.floor rounds towards negative infinity (lesson 17).
Format to exactly two decimal places.
console.log(price.(2));
toFixed returns a string with fixed decimals (lesson 16).
Functions
Complete the arrow function that doubles a number.
const double = n n * 2;
Single-expression arrow functions return their value implicitly (lesson 23).
Collect any number of arguments into an array.
function sum() {
return numbers.reduce((a, b) => a + b, 0);
}
Rest parameters start with ... (lesson 24).
Create a bound copy whose this is always user.
const greet = user.greet.(user);
bind returns a new function with a fixed this (lesson 27).
Arrays and objects
Add an item to the end of the array.
cart.("apple");
push adds to the end; unshift adds to the start (lesson 29).
Create a new array with every price doubled.
const doubled = prices.(p => p * 2);
map transforms every item into a new array (lesson 31).
Keep only the adults.
const adults = people.(p => p.age >= 18);
filter keeps items where the callback returns true (lesson 31).
Add up all the numbers.
const total = numbers.((sum, n) => sum + n, 0);
reduce combines items into a single value (lesson 31).
Sort numbers in ascending order.
scores.sort((a, b) => );
A negative result puts a first (lesson 32).
Pull name and age out of the object.
const { } = user;
Object destructuring matches by property name (lesson 33).
Merge two objects into a new one.
const settings = { ...defaults, };
Later spread properties override earlier ones (lesson 33).
Get all of an object's values as an array.
const values = Object.(scores);
Object.keys / values / entries (lesson 37).
Turn an object into a JSON string.
const text = JSON.(data);
JSON.stringify converts values to JSON text (lesson 41).
Classes, DOM and async
Call the parent class constructor.
class Dog extends Animal {
constructor(name) {
(name);
}
}
super() must run before using this (lesson 40).
Select the first element with the class "card".
const card = document.(".card");
querySelector takes any CSS selector (lesson 42).
Run a function when the button is clicked.
button.("click", handleClick);
Pass the function itself, without parentheses (lesson 44).
Stop the form from reloading the page.
form.addEventListener("submit", event => {
event.();
});
preventDefault cancels the browser's default action (lesson 44).
Wait for the promise inside an async function.
const response = fetch(url);
await pauses the async function until the promise settles (lesson 53).
Wait for several promises at the same time.
const [user, posts] = await Promise.([loadUser(), loadPosts()]);
Promise.all runs promises in parallel (lesson 52).
Coding problems
1. Reverse words
Write reverseWords(sentence) that reverses the order of the words: "one two three" → "three two one".
Show solution
function reverseWords(sentence) { return sentence.trim().split(/\s+/).reverse().join(" "); } console.log(reverseWords("one two three"));
three two one
2. Count vowels
Write countVowels(text) that returns how many vowels (a, e, i, o, u, either case) the text contains.
Show solution
function countVowels(text) { return (text.match(/[aeiou]/gi) ?? []).length; } console.log(countVowels("JavaScript Is Fun"));
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.
Show solution
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));
{ 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.
Show solution
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));
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.
Show solution
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);
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.
Show solution
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));
attempt 1 failed attempt 2 failed success!
Note the return await: without await, a rejection would escape the try/catch.