ES Modules

The Course
•
4 min read

A file can publish a small interface

An ES module has its own scope. export function totalMinutes(...) makes a function available; import { totalMinutes } from "./totals.js" brings that named export into another module. The braces name exports to import; this is module syntax, not an object being copied. Names must match unless you explicitly rename an import with as.

The relative path starts with ./ for the current directory. Use the .js extension in browser modules. A module runs when it is loaded, so keep reusable modules free of surprise printing or changes to the page. Put startup work in the entry file. Importing a function does not call it.

The multi-file editor below runs main.js. Open totals.js to inspect the exported function, then return to main.js and run it. Its output should be 45 and 0. Break the import name deliberately, read the error, and restore it. This is a real module relationship, not a comment pretending to import a file.

Browser modules normally need an HTTP-served page with a script of type=module. Double-clicking local HTML is unreliable for relative module imports. This course’s editor supplies the environment. Day 7 provides a downloadable project with a small local server and explicit commands. You do not need to install Node to complete these in-page lessons.

Predict and trace

Write the output before running. Follow the values through each call; if your prediction differs, identify the first step that surprised you.

Predict, then run JavaScript
// A reusable function has no printing side effect.
function totalMinutes(records) {
  let total = 0;

  for (const record of records) {
    total += record.minutes;
  }

  return total;
}

console.log(totalMinutes([{ minutes: 20 }, { minutes: 25 }]));
console.log(totalMinutes([]));
Check your prediction
45
0

The console example shows the function’s behavior. The file tabs below separate its definition from the calls.

Open the file tabs

Two real modules JavaScript
import { totalMinutes } from "./totals.js"; console.log(totalMinutes([{ minutes: 20 }, { minutes: 25 }])); console.log(totalMinutes([])); export function totalMinutes(records) { let total = 0; for (const record of records) { total += record.minutes; } return total; }
Check your prediction
45
0

Editing a file tab changes that file; Run starts main.js. An export is part of the module’s public contract, so changing its name requires updating its importers too.

Build it yourself

Exercise

ES Modules: practise

Write titles(books), the function you would export from a model module. Return an array of titles without printing inside the function. Print its joined result and an empty length.

Your working space JavaScript
// Keep model code independent of the DOM.
Hint 1: the idea

Map the valid records to their title fields.

Hint 2: a first step

The caller, not titles, should format or print the array.

Show one solution
function titles(books) {
  return books.map(book => book.title);
}

console.log(titles([{ title: "Notes" }, { title: "The Web" }]).join(", "));
console.log(titles([]).length);
Notes, The Web
0

In the file editor, add export before a new titles function in totals.js and import it in main.js. Keep both files free of document access. Explain which file owns startup.

Test a changed requirement

In the file editor, add export before a new titles function in totals.js and import it in main.js. Keep both files free of document access. Explain which file owns startup.

Explain before moving on

What crosses the module boundary? Why should a calculation module not query a form?

Where asynchronous module examples run

This file-tab editor supports this synchronous import example. It does not support top-level await in its entry file. Use the single-program editors and the async main entry point introduced on Day 3 for asynchronous examples. The Day 6 controller walkthrough combines its source functions for that editor, while the downloaded project runs their normal ES modules in Node or the browser. This is a limit of this practice editor, not a rule forbidding top-level await in ES modules.

Going further

Read MDN’s module guide after working through the examples. Use it as a reference when you meet an unfamiliar option; finishing every reference section is not required for this course.

Was this article helpful?

Your response is saved on this device.