Warm-up · Activity 1 of 7
// B2.5 · ~37 min · Beginner
Build: a unit converter
After this build you can turn text inputs into numbers, check them, convert them with named constants and print tidy results such as 42.195 km = 26.22 mi.
Lesson 5 of 5 in B2 Grammar, types and operators
You will be able to
- Keep conversion factors in named constants and convert with the right formula
- Format results with toFixed and template literals
- Check input values with typeof, Number() and Number.isNaN before converting them
Predict · Activity 2 of 7
Predict before you read on: the input arrives as text. What does this print?
const km = "10"; console.log(km + 5, Number(km) + 5);Practice · Activity 3 of 7
Fill in the method that rounds the miles to two decimals, so that the program prints 6.21.
const KM_PER_MILE = 1.609344; const km = 10; const miles = km / KM_PER_MILE; console.log(miles.____(2));console.log(miles.(2));Practice · Activity 4 of 7
What does this print?
console.log(typeof "12", typeof Number("12"), typeof Number("12 km"));Practice · Activity 5 of 7
Match each expression to what console.log prints for it.
Brain teaser · Activity 6 of 7
Brain teaser. What does this print?
const total = 0.1 + 0.2; console.log(total.toFixed(2), total.toFixed(2) === 0.3);Apply · Activity 7 of 7
Mini-task. Write the whole converter from scratch: the two factors as constants, three inputs as text (a distance, a mass and a temperature), their types before and after Number(), one line per conversion formatted with toFixed and a template literal, and a last line that checks a bad input such as "12 km" with Number.isNaN. Then change an input and predict the output.
Check your work against this list
Build it yourself
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
The unit converter
The three inputs are written into the program as text, because the editor has no keyboard input; a form on a page would give text too. The program shows the type before and after Number(), converts each value with a named factor or formula, and prints tidy results. The last line shows what a bad input turns into. Change an input, or the number of decimals, and predict the output before you run it again.
main.js
// A unit converter. The inputs are text, as a form field would give them.
const KM_PER_MILE = 1.609344;
const KG_PER_POUND = 0.45359237;
const distanceInput = "42.195";
const massInput = "70";
const celsiusInput = "21.5";
console.log(`Before: ${typeof distanceInput}`);
const km = Number(distanceInput);
const kg = Number(massInput);
const celsius = Number(celsiusInput);
console.log(`After: ${typeof km}`);
console.log(`${km} km = ${(km / KM_PER_MILE).toFixed(2)} mi`);
console.log(`${kg} kg = ${(kg / KG_PER_POUND).toFixed(1)} lb`);
console.log(`${celsius} °C = ${(celsius * 9 / 5 + 32).toFixed(1)} °F`);
const badInput = "12 km";
const bad = Number(badInput);
console.log(`"${badInput}" is NaN: ${Number.isNaN(bad)}`);
Run it with
node main.jsOutput
Before: string
After: number
42.195 km = 26.22 mi
70 kg = 154.3 lb
21.5 °C = 70.7 °F
"12 km" is NaN: true- typeof shows the change: the input is a string, the converted value a number.
- Each factor is written once, in a const, and used by name.
- toFixed(2) and toFixed(1) round only what is printed; km and kg keep their full values.
- "12 km" is not a number as a whole, so Number gives NaN, and Number.isNaN reports it.
Change it and run 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.
Exercises
Exercise 1 of 3
Step 1: kilometres to miles
Convert two distances, given as text, into miles: "10" and "21.0975". Convert each input with Number(), divide by KM_PER_MILE, and print one line each, with the miles rounded to two decimals: 10 km = 6.21 mi and 21.0975 km = 13.11 mi. Use a template literal for each line.
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.
Hints
Hint 1
Run the starter: the miles come out as 6.2137119223733395. toFixed(2) rounds that to 6.21.
Hint 2
Put brackets around the division before .toFixed: (km / KM_PER_MILE).toFixed(2).
Hint 3
A template literal builds the line: `${km} km = ${(km / KM_PER_MILE).toFixed(2)} mi`. Do the same for the second input.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const KM_PER_MILE = 1.609344;
const distanceInput = "10";
const halfMarathonInput = "21.0975";
const km = Number(distanceInput);
console.log(`${km} km = ${(km / KM_PER_MILE).toFixed(2)} mi`);
const halfKm = Number(halfMarathonInput);
console.log(`${halfKm} km = ${(halfKm / KM_PER_MILE).toFixed(2)} mi`);
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
const KM_PER_MILE = 1.609344;
const distanceInput = "10";
const halfMarathonInput = "21.0975";
// Print: 10 km = 6.21 mi
console.log(distanceInput, "km =", distanceInput / KM_PER_MILE, "mi");
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
const lines = async () => (await runMain()).trimEnd().split('\n');
test('converts 10 km', async () => {
const got = await lines();
assert.equal(got[0], '10 km = 6.21 mi', `the first line is ${JSON.stringify(got[0])}, expected "10 km = 6.21 mi"`);
});
test('converts the half marathon', async () => {
const got = await lines();
assert.equal(got[1], '21.0975 km = 13.11 mi', `the second line is ${JSON.stringify(got[1])}, expected "21.0975 km = 13.11 mi"`);
});
test('prints exactly two lines', async () => {
const got = await lines();
assert.equal(got.length, 2, `the program printed ${got.length} line(s), expected 2`);
});
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 3
Step 2: check the inputs
Before converting, show what the inputs are. Print massInput: string (the type of the input), convert it with Number() and print kg: number, then print the mass in pounds with one decimal: 70 kg = 154.3 lb. Last, convert heightInput and print "1,80" is NaN: true, with the input in double quotes and the check done by Number.isNaN.
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.
Hints
Hint 1
typeof massInput gives "string"; in a template literal: `massInput: ${typeof massInput}`.
Hint 2
A pound is KG_PER_POUND kilograms, so pounds are kg / KG_PER_POUND. Round with .toFixed(1).
Hint 3
Double quotes can stand inside backticks as they are: `"${heightInput}" is NaN: ${Number.isNaN(height)}`.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const KG_PER_POUND = 0.45359237;
const massInput = "70";
const heightInput = "1,80";
console.log(`massInput: ${typeof massInput}`);
const kg = Number(massInput);
console.log(`kg: ${typeof kg}`);
console.log(`${kg} kg = ${(kg / KG_PER_POUND).toFixed(1)} lb`);
const height = Number(heightInput);
console.log(`"${heightInput}" is NaN: ${Number.isNaN(height)}`);
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
const KG_PER_POUND = 0.45359237;
const massInput = "70";
const heightInput = "1,80";
// 1. Print the type of massInput, convert it, print the type of kg.
// 2. Print the mass in pounds, with one decimal.
// 3. Convert heightInput and print whether the result is NaN.
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
const lines = async () => (await runMain()).trimEnd().split('\n');
test('shows the types before and after Number()', async () => {
const got = await lines();
assert.deepEqual(got.slice(0, 2), ['massInput: string', 'kg: number'], `the first two lines are ${JSON.stringify(got.slice(0, 2))}`);
});
test('converts 70 kg to pounds', async () => {
const got = await lines();
assert.equal(got[2], '70 kg = 154.3 lb', `the third line is ${JSON.stringify(got[2])}, expected "70 kg = 154.3 lb"`);
});
test('finds that "1,80" is not a number', async () => {
const got = await lines();
assert.equal(got[3], '"1,80" is NaN: true', `the fourth line is ${JSON.stringify(got[3])}, expected ${JSON.stringify('"1,80" is NaN: true')}`);
});
test('prints exactly four lines', async () => {
const got = await lines();
assert.equal(got.length, 4, `the program printed ${got.length} line(s), expected 4`);
});
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 3 of 3
Step 3: temperatures both ways
This part converts 21.5 °C to Fahrenheit and 98.6 °F to Celsius, but the second line is wrong and neither is tidy. It should print 21.5 °C = 70.7 °F and 98.6 °F = 37.0 °C. Fix the order of the calculation in the second formula and round both results to one decimal. There is no error message: compare the output with what it should be.
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.
Hints
Hint 1
The starter prints 80.82222222222222 for 98.6 °F: 32 * 5 / 9 is worked out first, and then subtracted.
Hint 2
Brackets decide the order: (fahrenheit - 32) * 5 / 9.
Hint 3
Wrap each whole calculation in brackets and add .toFixed(1): 37 becomes "37.0".
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const celsiusInput = "21.5";
const fahrenheitInput = "98.6";
const celsius = Number(celsiusInput);
const fahrenheit = Number(fahrenheitInput);
console.log(`${celsius} °C = ${(celsius * 9 / 5 + 32).toFixed(1)} °F`);
console.log(`${fahrenheit} °F = ${((fahrenheit - 32) * 5 / 9).toFixed(1)} °C`);
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
const celsiusInput = "21.5";
const fahrenheitInput = "98.6";
const celsius = Number(celsiusInput);
const fahrenheit = Number(fahrenheitInput);
console.log(`${celsius} °C = ${celsius * 9 / 5 + 32} °F`);
console.log(`${fahrenheit} °F = ${fahrenheit - 32 * 5 / 9} °C`);
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
const lines = async () => (await runMain()).trimEnd().split('\n');
test('converts 21.5 °C to Fahrenheit', async () => {
const got = await lines();
assert.equal(got[0], '21.5 °C = 70.7 °F', `the first line is ${JSON.stringify(got[0])}, expected "21.5 °C = 70.7 °F"`);
});
test('converts 98.6 °F to Celsius, with one decimal', async () => {
const got = await lines();
assert.equal(got[1], '98.6 °F = 37.0 °C', `the second line is ${JSON.stringify(got[1])}, expected "98.6 °F = 37.0 °C"`);
});
test('prints exactly two lines', async () => {
const got = await lines();
assert.equal(got.length, 2, `the program printed ${got.length} line(s), expected 2`);
});
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.jsCommon mistakes
toFixed on the text input
const distanceInput = "42.195";
console.log(distanceInput.toFixed(2));
What Node.js prints
TypeError: distanceInput.toFixed is not a functionWhy, and the fix
toFixed is a method of numbers, and distanceInput is still a string, which has no toFixed. Convert first, then format: Number(distanceInput).toFixed(2), or better, keep the number in its own const km = Number(distanceInput); and call km.toFixed(2) when you print.
Changing a conversion factor
const KM_PER_MILE = 1.609344;
KM_PER_MILE = 1.6;
What Node.js prints
TypeError: Assignment to constant variable.Why, and the fix
A const cannot be given a new value, and that is the point of a factor in a const: no line can round or change it by accident. If you want a shorter number in the output, round the result with toFixed when you print it, and leave the factor as it is.
A template literal without its closing backtick
const km = 5;
console.log(`${km} km);
What Node.js prints
SyntaxError: Unexpected end of inputWhy, and the fix
A template literal starts and ends with a backtick. Without the closing one, JavaScript reads the rest of the file as part of the text and reaches the end still inside it. As with every SyntaxError, no line runs. Close it: console.log(`${km} km`);.
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
Exit ticket
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.