JavaScript Scripts and Modules
Understand ECMAScript Scripts and Modules, import/export forms, live bindings, module namespaces, dependency linking and evaluation, cycles, top-level await, dynamic import, import attributes, and JSON modules without confusing language semantics with browser loading.
Advanced
Scripts and modules are different execution units
ECMAScript defines two source-text goals for program-level code: Script and Module. A Script is evaluated as a script; a Module is parsed and evaluated with module-specific syntax and semantics. This lesson owns the language-level boundary between them. Browser loading rules such as HTML script elements, URLs, MIME checks, and fetching are host-platform concerns and are intentionally outside this lesson.
Output
Ready to run.
Quick check
Which concept belongs primarily to this lesson?
Export values deliberately
A module can expose bindings with named exports or one default export. The export declaration describes the module interface; it does not copy a value into another module. Exporting a binding makes that binding available to the module graph.
Output
Ready to run.
Quick check
Which statement is true about a module default export?
Import named, default, and namespace bindings
Static imports choose the bindings a module needs from another module. Named imports select specific exports, a default import selects the default export, and a namespace import creates a module namespace object binding that exposes the module’s exported names.
Output
Ready to run.
Quick check
What does `import * as ns from "./source.js"` bind?
Imported bindings are live
Static imports are live bindings rather than snapshots. If the exporting module changes an exported mutable binding, an importer observes the current binding. The importer cannot reassign the imported binding itself.
Output
Ready to run.
Quick check
After `increment()` changes the exported `count`, what does an importer observe?
Module namespace objects expose the module interface
A module namespace object represents the exports of a module. Namespace properties correspond to exported names and are ordered according to the module namespace semantics rather than being ordinary mutable application state. Treat it as an interface view, not a bag of writable variables.
Output
Ready to run.
Quick check
What is the useful mental model for a module namespace object?
Re-export without becoming the original owner
A module can re-export another module’s bindings. This lets a package-style entry module define a public surface without copying implementations into one file. `export { ... } from` and `export * from` create forwarding relationships in the module graph.
Output
Ready to run.
Quick check
Why use a re-exporting entry module?
Static imports form a dependency graph
Static imports are known from the module source before evaluation. The host loads requested modules, while ECMAScript defines how the resulting Module Records are linked and evaluated. Think in terms of a graph: modules are nodes and import relationships are edges.
Output
Ready to run.
Quick check
What does a static import contribute before evaluation?
Linking resolves bindings before evaluation
Module linking prepares the connected graph so imported and exported bindings can be resolved before module code runs. This separation matters: a module can have a valid dependency structure even though its executable statements have not yet evaluated.
Output
Ready to run.
Quick check
What is the main purpose of module linking?
Cycles are part of the module model
Module graphs may contain cycles. ECMAScript has explicit module-record machinery for cyclic dependencies so linking and evaluation can reason about strongly connected groups. A cycle is not automatically an error; what matters is whether the code attempts to use a binding before that binding has been initialized.
Output
Ready to run.
Quick check
Does the existence of an import cycle automatically make a module graph invalid?
Top-level await makes module evaluation asynchronous
A module can contain `await` at top level. Such a module is individually asynchronous, and its dependants may have to wait for its evaluation to complete. This is module evaluation behavior; the general semantics of Promise objects and async functions remain owned by their dedicated lessons.
Output
Ready to run.
Quick check
What is special about top-level `await` in a module?
Dynamic import loads a module from an expression
The `import()` expression performs a dynamic module import and produces a Promise for the module namespace object. Unlike static import declarations, it can be evaluated conditionally or in response to runtime decisions. Promise semantics remain the responsibility of the Promises lesson.
Output
Ready to run.
Quick check
What does `import("./feature.js")` produce?
Import attributes are part of the module request
Current ECMAScript module requests can carry import attributes. The syntax uses a `with` clause, and the module request records retain the attribute key/value pairs. The host decides how resources are loaded, while ECMAScript defines the language-level representation and behavior of the request.
Output
Ready to run.
Quick check
Where does `type: "json"` belong in the ECMAScript module model?
JSON modules have a defined module record form
ECMAScript defines JSON module records as a module form associated with a JSON import request. The JSON is parsed into the module’s exported value rather than being treated as JavaScript source code. This lesson covers the language-level module relationship; browser fetch and MIME handling remain host concerns.
Output
Ready to run.
Quick check
How should a JSON module be understood?
Modules are strict and have their own top-level binding rules
Module code is always strict mode code. Top-level declarations in a module are scoped to that module rather than becoming properties of the global object. This is one reason modules provide a stronger boundary than concatenating unrelated script code.
Output
Ready to run.
Quick check
Which statement describes module top-level bindings?
Static import syntax is intentionally constrained
Static import declarations are part of module syntax rather than ordinary runtime expressions. Their structure is known from source text, which allows the module graph to be analyzed before evaluation. When runtime decisions are needed, use dynamic `import()` instead.
Output
Ready to run.
Quick check
Which form is an expression that can be evaluated conditionally?
Keep host behavior separate from ECMAScript module semantics
ECMA-262 defines the module language and Module Records, but hosts supply loading mechanisms. In a browser, HTML and Fetch determine how a module URL is requested and delivered. In another host, a different loader can provide the module source. This boundary prevents the JavaScript curriculum from teaching browser behavior as if it were part of the language.
Output
Ready to run.
Quick check
Which behavior belongs to a future browser-scripting lesson rather than this ECMAScript module lesson?
Use modules as explicit dependency boundaries
A practical module boundary has a small public surface, clear ownership, and dependencies that point in intentional directions. Re-exporting can define an API entry point, while internal modules remain implementation details. This connects module semantics to program architecture without duplicating the architecture lesson’s broader design material.
Output
Ready to run.
Quick check
What makes a module boundary useful?
Know what this lesson owns
Scripts and Modules owns ECMAScript’s Script/Module distinction, import/export syntax, live bindings, namespace objects, module dependency linking and evaluation, cycles, top-level await, dynamic import, import attributes, and JSON modules. It does not replace the lessons for parsing, Promises, async functions, execution contexts, or browser loading. Those boundaries keep the curriculum coherent instead of repeating the same semantics in multiple places.
Output
Ready to run.
Quick check
Why does Foxipa keep these boundaries explicit?
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.