Loading...

JavaScript Modules

JavaScript modules split a program into files. An export exposes a value, and an import consumes it. Our examples use the visible line lida / tea / mint.

Export named values

A named export gives a value an explicit name. A module can expose several named values.

Create math.js

javascript
// math.js
export const drink = "tea";
export function label(name) {
return `${name} / ${drink} / mint`;
}

The drink constant and label function are available to other modules because each is exported. Code that is not exported stays inside math.js.

Import named values

Use braces with the same names when importing named exports.

Use named exports in app.js

javascript
// app.js
import { drink, label } from "./math.js";

console.log(drink);
console.log(label("lida"));

The import reads the exported bindings; it does not copy a separate, unrelated definition into the file. In a browser, these files need to be served over HTTP or HTTPS.

Export one default value

A default export represents the main value of a module. The importing file chooses its local name and does not use braces.

Create and import a default

javascript
// greeting.js
export default function greet(name) {
return `Hello, ${name}!`;
}

// app.js
import greet from "./greeting.js";
console.log(greet("lida"));

Named imports use { drink, label }; a default import uses the chosen name greet. A file can have one default export and may also have named exports.

Module scope and dynamic import

Top-level declarations in a module are module-scoped, not properties of window. Dynamic import loads a module later and returns a Promise.

Keep a secret private and load later

javascript
// menu.js
const secret = "not global";
export const items = ["tea", "mint"];

// app.js
import("./menu.js").then((menu) => {
console.log(menu.items.join(" / "));
});
console.log(window.secret); // undefined

Only items crosses the module boundary. The dynamic import result is a module namespace object, so its exported values are read as properties. The example assumes menu.js is served by a web server.

See module behavior in one page

The following self-contained demo creates module source in memory, turns it into Blob URLs, and imports it. This avoids requiring a project folder, although real applications usually keep the modules in separate files.

Run a browser module demo

html
<p id="result"></p>
<script type="module">
const source = `
export const drink = "tea";
export function label(name) { return name + " / " + drink + " / mint"; }
`;
const url = URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
const module = await import(url);
document.querySelector("#result").textContent = module.label("lida");
URL.revokeObjectURL(url);
</script>

The page displays exactly lida / tea / mint. type="module" enables module syntax, and the Blob URL supplies the module without a network request.

In a normal project, move the source into math.js and the importing code into app.js, then load the entry file with <script type="module" src="./app.js"></script>. Opening that file directly with file:// is not a reliable way to test browser modules; use an HTTP server.

📊 Module choices

Syntax Purpose Example
Named export/import Share specific names export const drink = "tea" / import { drink } ...
Default export/import Share the module's main value export default function greet() / import greet ...
Dynamic import Load later and receive a Promise import("./menu.js").then(...)
Module scope Keep top-level declarations private const secret = "not global"

Practical exercise

Create math.js with named exports drink and label, then import them in app.js. Add a default greet function in greeting.js, and make the page show lida / tea / mint.

Common mistakes

Do not omit braces around named imports, do not use two default exports in one file, and do not expect an unexported top-level variable to be global. Browser modules need an HTTP(S) server.

Key point

Modules create file boundaries: export makes selected bindings available, import uses them, default imports use a chosen name, and module scope protects unexported declarations.
Keep each module focused, name imports clearly, and revoke temporary Blob URLs after the demo no longer needs them.

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

❓
6
Questions
🎯
70%
To Pass
♾️
∞
Time
🔄
∞
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top