Async & Modern JSIntermediate6 min20 / 23

ES Modules

Split code across files with import and export — named exports, default exports, and how modules keep scope clean.

As programs grow you split them across files. ES Modules are the standard way to share code between files with export and import. Each module has its own scope — nothing leaks into the global namespace unless you export it.

math.js — named exports
export const PI = 3.14159;

export function add(a, b) {
  return a + b;
}

export function square(x) {
  return x * x;
}
app.js — import what you need
import { add, PI } from './math.js';

console.log(add(2, 3)); // 5
console.log(PI);        // 3.14159

Named exports are imported by their exact name inside braces. You can rename on import with as: import { add as sum } from './math.js'.

#Default exports

one main export per module
// logger.js
export default function log(msg) {
  console.log('[app]', msg);
}

// app.js — no braces, you pick the name
import log from './logger.js';
log('ready');
Tip

Named vs default

Use named exports when a file exposes several things (utilities, constants). Use a default export for a module's single main thing (a component, a class). A file can have many named exports and at most one default.

Quick check

How do you import a default export from './Button.js'?

Key takeaways

  • Modules have their own scope — share code only via `export`.
  • Named exports import by name in braces: `import { add } from './math.js'` (rename with `as`).
  • A default export imports without braces and you name it yourself.
  • A file can have many named exports but only one default export.
  • In browsers, use `<script type="module">`; in Node, `.mjs` or `"type": "module"`.
Practice challenges
Test yourself · earn XP
0/3
Fix the bug#1

`add` is a named export, but this import fails. What's wrong?

fix-bug
// math.js
export function add(a, b) { return a + b; }

// app.js
import add from './math.js';
Predict the output#2

Given `export default function greet() { return 'hi'; }`, which import is correct?

predict-output
// which line correctly imports the default?
Fill in the blank#3

Complete the line to export PI as a named export.

 const PI = 3.14159;
Your turn
Practice exercise

In utils.js, export a named function capitalize(s) and a default function slugify(s). Then write the two import lines in app.js to bring both in.

Try it live — edit the code and hit Run to see the output:

solution.js · editable