A module is a relatively self-contained cluster of code with a public interface and hidden implementation details. It is larger than a function or object: instead of growing one monolithic program, you group related functionality into smaller, loosely coupled units that are easier to understand, maintain, and reuse. Hiding internals also reduces accidental changes and naming clashes. section 11.0 section 11.1
There are several ways to make that boundary in JavaScript:
- Before ES6, the module pattern combines an immediately invoked function, which creates a private scope, with closures, which keep its variables available to returned public functions. The returned object serves as the interface. section 11.3
- AMD defines asynchronously loaded modules and can resolve dependencies automatically; CommonJS uses simpler syntax and synchronous loading, making it more suited to server-side JavaScript. section 11.3
- ES6 modules are file based. `export` makes selected identifiers available to other modules; `import` brings them in. Unexported identifiers remain inside the module, even when declared at its top level. section 11.2
Listing 11.5. Exporting from a Ninja.js module
const ninja = "Yoshi"; #A
export const message = "Hello"; #B
#B
export function sayHiToNinja() { #B
return message + " " + ninja; #C
}
Notice the boundary: `message` and `sayHiToNinja` are exported, but `ninja` is not. The exported function can still use `ninja` internally. section 11.2.1
Listing 11.7. Importing from the Ninja.js module
import { message, sayHiToNinja} from "Ninja.js"; #A
assert(message === "Hello", #B
"We can access the imported variable"); #B
assert(sayHiToNinja() === "Hello Yoshi", #B
"We can say hi to Yoshi from outside the module"); #B
assert(typeof ninja === "undefined", #C
"But we cannot access Yoshi directly"); #C
The importing file can call the exported function and read the exported message, but cannot access the unexported `ninja` identifier directly. section 11.2.1
An ES6 module can also have a single default export. Named exports and imports can use aliases when a different name better fits the caller or avoids a clash; `import * as` gathers named exports under one name. Where browsers do not support the module syntax, transpilation with Babel, Traceur, or TypeScript, or loading through SystemJS, is an option. section 11.2.1 section 11.2
Quick check: if an imported module contains a top-level variable but does not export it, can the importing file use that identifier? No—the module’s interface consists of what it explicitly exports. section 11.2 section 11.4


































