Modules Before ES6
Before ES6, JavaScript did not have a built-in module system. Early on that was not a problem, because JavaScript was mostly used for small tasks like form validation and DOM manipulation. As applications got bigger, the community came up with its own patterns to encapsulate code.
Immediately Invoked Function Expressions (IIFEs)
An IIFE is a function that is defined and immediately invoked. Here is the syntax:
(function () {
// statements
})();
It contains two parts:
- A function expression wrapped in parentheses:
(function () { ... }) - The immediate invocation:
()right after the function
Consider a simple script that declares a variable:
// script.js
const pi = 3.14159;
This adds pi to the global scope. To encapsulate the variable within an IIFE:
// script.js
(function () {
const pi = 3.14159;
console.log(pi); // 3.14159
})();
When you run this script, the value prints to the console. But if you try to access pi in the global scope, you get a ReferenceError, because pi is encapsulated within the IIFE.
IIFEs were a common pattern for encapsulation before ES6. They still have uses, but modules give us a more structured and standard way to do this.
CommonJS Modules
Before ES6 modules, the CommonJS module system was widely used in Node.js. CommonJS modules are synchronous and use require to import and module.exports to export.
Here is a CommonJS module:
// account.js
let balance = 0;
const INTEREST_RATE = 0.2;
function deposit(amount) {
balance += amount;
}
function withdraw(amount) {
balance -= amount;
}
function getBalance() {
return balance;
}
module.exports = {
INTEREST_RATE,
deposit,
withdraw,
getBalance,
};
The module.exports is an object. Any value assigned to it will be exported from the module.
To import these values:
// script.js
const { deposit, withdraw, getBalance } = require("./account.js");
console.log(getBalance()); // 0
deposit(100);
withdraw(20);
console.log(getBalance()); // 80
Unlike ES6 import statements, require can be conditional and placed anywhere in the code.
ES6 Modules vs CommonJS
| Feature | ES6 Modules | CommonJS |
|---|---|---|
| Loading | Asynchronous | Synchronous |
| Syntax | import / export |
require / module.exports |
| Static analysis | Yes | No |
| Placement | Top of file only | Anywhere |
| Default in Node.js | No (requires config) | Yes |
CommonJS is still used in Node.js, but ES6 modules are the standard for JavaScript now. They are asynchronous, which is better for browsers. They allow static analysis, which is better for tooling. And the syntax is the one the language itself defines.