Warm-up · Activity 1 of 7
Warm-up from lesson I3.1. add has no export. What does main.js print?
// math.js
function add(a, b) {
return a + b;
}
// main.js
import {add} from "./math.js";
console.log(add(1, 2));// I3.2 · ~34 min · Intermediate
After this lesson you choose between named exports and a default export, import both correctly, rename with as, and build an index module that gathers other modules.
You will be able to
Warm-up · Activity 1 of 7
// math.js
function add(a, b) {
return a + b;
}
// main.js
import {add} from "./math.js";
console.log(add(1, 2));Predict · Activity 2 of 7
// math.js
export function add(a, b) {
return a + b;
}
export default function square(x) {
return x * x;
}
// main.js
import add from "./math.js";
console.log(add(3, 4));Practice · Activity 3 of 7
export ____ function greet(name) {
return "Hello, " + name;
}Practice · Activity 4 of 7
Practice · Activity 5 of 7
// math.js
export function add(a, b) {
return a + b;
}
export default function square(x) {
return x * x;
}
// main.js
import * as math from "./math.js";
console.log(Object.keys(math));Brain teaser · Activity 6 of 7
// math.js
export function add(a, b) {
return a + b;
}
export default function square(x) {
return x * x;
}
// index.js
export * from "./math.js";
// main.js
import square from "./index.js";
console.log(square(5));Apply · Activity 7 of 7
Check your work against this list
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
text.js has two named exports and a default export. numbers.js has one named export. utils.js is an index module: it passes on the named exports of text.js, renames round2 to round, and turns text.js’s default into a named slugify. main.js imports the default under its own name, renames capitalize, and takes utils.js as a namespace object.
main.js
import makeSlug, {capitalize as cap} from "./text.js";
import * as utils from "./utils.js";
console.log(makeSlug("Named And Default"));
console.log(cap("module"));
console.log(Object.keys(utils));
console.log(utils.round(3.14159), utils.shout("hi"));
text.js
export function capitalize(word) {
return word[0].toUpperCase() + word.slice(1);
}
export function shout(text) {
return text.toUpperCase() + "!";
}
// The one default export of this file.
export default function slugify(title) {
return title.toLowerCase().split(" ").join("-");
}
numbers.js
export function round2(n) {
return Math.round(n * 100) / 100;
}
utils.js
// An index module: it gathers features from other files.
export * from "./text.js"; // every named export, but not the default
export {round2 as round} from "./numbers.js";
export {default as slugify} from "./text.js";
Run it with
node main.jsOutput
named-and-default
Module
[ 'capitalize', 'round', 'shout', 'slugify' ]
3.14 HI!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.
Exercise 1 of 2
main.js should export formatPrice(cents) as its default export, which turns 1999 into "19.99 EUR", and two named exports: CURRENCY ("EUR") and parsePrice(text), which turns "19.99" into 1999. The starter exports formatPrice by name, so a file that imports the default gets nothing. Make it the default export.
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.
Run the tests: the module has no default export. Which word turns an export into the default?
A module has at most one default export; the other two stay named.
export default function formatPrice(cents) { … }
One way to solve it. Yours can look different and still pass the checks.
export const CURRENCY = "EUR";
export default function formatPrice(cents) {
return (cents / 100).toFixed(2) + " " + CURRENCY;
}
export function parsePrice(text) {
return Math.round(Number(text) * 100);
}
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
export const CURRENCY = "EUR";
export function formatPrice(cents) {
return (cents / 100).toFixed(2) + " " + CURRENCY;
}
export function parsePrice(text) {
return Math.round(Number(text) * 100);
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import * as prices from './main.js';
test('The default export formats cents', () => {
assert.equal(typeof prices.default, 'function', 'main.js has no default export function');
const got = prices.default(1999);
assert.equal(got, '19.99 EUR', `the default export gave ${got}`);
});
test('CURRENCY and parsePrice are named exports', () => {
assert.equal(prices.CURRENCY, 'EUR', `CURRENCY is ${prices.CURRENCY}`);
assert.equal(prices.parsePrice('19.99'), 1999, 'parsePrice should turn 19.99 into 1999');
});
test('formatPrice is the default, not also a named export', () => {
assert.equal('formatPrice' in prices, false, 'formatPrice should be exported only as the default');
});
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 2
text.js and numbers.js are given. main.js is the index module of a small library: it should export exactly capitalize (named, from text.js), round (numbers.js’s round2, renamed) and slugify (text.js’s default, as a named export). The starter uses export * twice, which passes on round2 under its old name and leaves out the default.
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.
Run the tests: the index exports round2 and no slugify. Which form re-exports one name and can rename it?
export {round2 as round} from "./numbers.js"; renames while passing it on.
A default is passed on by its name default: export {default as slugify} from "./text.js";
One way to solve it. Yours can look different and still pass the checks.
export {capitalize} from "./text.js";
export {round2 as round} from "./numbers.js";
export {default as slugify} from "./text.js";
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
export * from "./text.js";
export * from "./numbers.js";
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import * as lib from './main.js';
test('The index exports exactly capitalize, round and slugify', () => {
const names = Object.keys(lib);
assert.deepEqual(names, ['capitalize', 'round', 'slugify'], `main.js exports ${JSON.stringify(names)}`);
});
test('The re-exported functions work', () => {
assert.equal(lib.capitalize('ada'), 'Ada', 'capitalize should give Ada');
assert.equal(lib.round(3.14159), 3.14, 'round should round to 2 decimals');
assert.equal(lib.slugify('Hello World'), 'hello-world', 'slugify should give hello-world');
});
text.js
export function capitalize(word) {
return word[0].toUpperCase() + word.slice(1);
}
export default function slugify(title) {
return title.toLowerCase().split(" ").join("-");
}
numbers.js
export function round2(n) {
return Math.round(n * 100) / 100;
}
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.jsimport add from "./math.js";
console.log(add(1, 2));
What Node.js prints
SyntaxError: The requested module './math.js' does not provide an export named 'default'Why, and the fix
Without braces, import asks for the default export, and math.js has none. Import the named export in braces: import {add} from "./math.js". Or, if add is meant to be the main thing the module offers, export it with export default.
export default const VAT = 0.19;
console.log("loaded");
What Node.js prints
SyntaxError: Unexpected token 'const'Why, and the fix
export default takes an expression, a function or a class, not a variable declaration. Declare first, then export: const VAT = 0.19; export default VAT;. Or write the value directly: export default 0.19;. Usually a named export, export const VAT = 0.19;, is clearer.
import * as math from "./math.js";
math.add = (a, b) => a - b;
console.log(math.add(5, 2));
What Node.js prints
TypeError: Cannot assign to read only property 'add' of object '[object Module]'Why, and the fix
A namespace object is sealed and its properties are read-only: it is a view of the module’s exports, which only the module can change. To use a different function, declare your own: const subtract = (a, b) => a - b;.
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
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.