JS Sketchbooksee JavaScript think ✏️
← back to phase 8

8.1 — Modules: import & export

Every program you’ve written fits in one file. No real project does: a Playwright test suite is dozens of files — tests, helpers, configuration, page models — working together. Split carelessly and nothing can find anything; the language’s answer is modules: one file = one sealed module, sharing only what it explicitly exports.

Two new keywords, export and import — and one new picture, the dependency graph — and you can read the folder structure of any professional codebase.

watch it happen
// ---- math.js ----------------
export const TAX = 0.25;

export function withTax(price) {
  return price * (1 + TAX);
}

const secret = "internal only";

// ---- cart.js ----------------
import { withTax } from "./math.js";

console.log(withTax(100));

First, the problem. Real projects are thousands of lines; one file becomes a junk drawer where every variable can see every other variable, and two far-apart lines can silently fight over one name. The fix has a name: MODULES.

app.js — 4,000 lines 😵everything sees everything — nothing is privateone giant file = a junk drawer — every name can see every other name
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

Precision on what travels: a named import is not a copy — it’s a live binding to the exporting module’s variable. If math.js reassigns an exported let counter, every importer sees the new value. You read through the door; you don’t take a photocopy home.

Each module runs once, no matter how many files import it. The first import executes the file and caches the result; every later import receives that same cached module. That’s why a module is a safe place for shared setup — and why test frameworks lean on this so heavily.

“Static” buys real things: because the graph is known before execution, the engine can report a misspelled import name immediately, and build tools can drop exports nobody imports (you’ll hear this called tree-shaking).

Job note: every Playwright test file you will ever write starts with import { test, expect } from "@playwright/test" — a named import from an installed package instead of a ./file path. Installing packages is exactly the next lesson.

your turn

⌨️ build the import machine

The sandbox runs a single file, so build the mechanism yourself: a module is a box of named things, and importing means fetching one OUT of the box by its name.

requirements:

  • Create TAX set to 0.25, a function withTax(price) returning price * (1 + TAX), and an object mathModule holding both under those exact names.
  • Write importFrom(module, name): it returns whatever the module holds under that name — the name arrives as a string variable, so pick the right property syntax (4.4 knows).
  • Use it twice: fetch "withTax" into a variable and print calling it with 100; then print fetching "TAX" directly.

when you press RUN, the console must show exactly:

125
0.25

✏️ Quick check 1

cart.js runs console.log(withTax(100)) with TAX = 0.25. What prints?

✏️ Quick check 2

math.js has const secret = "internal only" — with no export. Can cart.js import secret? Type yes or no.

✏️ Quick check 3

True or false: an import line may sit inside an if block, so you only load the module sometimes.

teach it back

🗣️ Now teach it back

Explain modules to a friend: why one giant file breaks down, what export and import each do, what a module can see of another module, and what the dependency graph is.

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
One file = one module = one sealed scope. Private by default; export opens a door, import { name } borrows through it — matched by exact name.
Imports are STATIC: the engine reads the whole dependency graph before running anything — top of file, never inside an if. Files + arrows = the dependency graph.
export default marks a file’s one main thing (imported without braces, any name). Browsers need <script type="module">; Node’s two systems wait in 9.3.
next: 8.2 npm & package.json →