Group of code and data related to a particular piece of functionality. It encapsulates implementation details and exposes a public API, and is combined with other modules to build a larger application.
- Create higher-level abstractions
- Encapsulation
- Reusability
- Simplify dependency management (in some cases every module should declare explicitly all the other dependent modules at the top, we'll see how to improve this)
Let's start with some patterns that we can use natively in browsers today.
- Reduces global scope pollution
- Anonymous function
- Invoked when declared
- Provides encapsulation
- Reduces the number of variables declared in the global scope
- No dependency management (far from ideal)
- Nice pattern to use if you're constrained to writing pure ES5 code
(function() {
console.log('Starting MultiMath with an IIFE');
// add click handler to the start game button
document.getElementById('startGame').addEventListener('click', function() {
player.setName(document.getElementById('playername').value);
game.printGame();
});
// add click handler to the calculate score button
document.getElementById('calculate').addEventListener('click', function() {
game.calculateScore();
});
// set the default number of problems
document.getElementById('problemCount').value = game.getProblemCount();
})();
- Most popular
- Nice encapsulation of private members
- Adds one value to global scope per module
- Clean syntax for exposing a public API for consumers of the module.
- No dependency management :(
- Pure JS that works in modern blowsers without any external libraries :)
- Comes in 2 flavours:
- Singleton (only one instance of the module in memory)
- Constructor (create as many as you need)
var player = function() {
// private members
var playerName = '';
function logPlayer() {
console.log('The current player is ' + playerName + '.');
}
function setName(newName) {
playerName = newName;
}
function getName() {
return playerName;
}
return {
logPlayer: logPlayer,
setName: setName,
getName: getName
};
}();
var Scoreboard = function() {
// private members
var message = '';
function printMessage() {
console.log(message);
}
return {
showMessage: printMessage
};
};
var myScoreboard = new Scoreboard();
myScoreboard.showMessage();
- Module formats and loaders are independant to each other but used together.
- Module format: Syntax
- Module Loader: Execution
- Relationship between module formats and loaders is like Javascript engine which exists on its own but needs a browser to interpret its syntax
- Asynchronous Module Definition (AMD)
- CommonJS
- Universal Module Definition (UMD)
- System.register
- ES2015 (first version of JS to provide built-in support for modules)
- RequireJS (AMD)
- SystemJS (AMD, CommonJS, UMD, System.register)