I just started learning patterns in JavaScript, and getting used to writing JavaScript like this:
(function(window){
var privateVar;
var privateFunc = function(param){
//do something
}
return{
publicFunc: function(){
do something
}
}(window));
But recently I found some scripts that write something like this in the beginning:
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('something', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.something = factory(root);
}
})(window || this, function (root) {
var privateVar;
var privateFunc = function(param){
//do something
}
return{
publicFunc: function(){
do something
}
});
So, what does this piece of code in the beginning mean? What is the difference between that and with this module export technique:
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
Module exports are the instructions that tell Node. js which bits of code (functions, objects, strings, etc.) to export from a given file so that other files are allowed to access the exported code.
When we want to export a single class/variable/function from one module to another module, we use the module. exports way. When we want to export multiple variables/functions from one module to another, we use exports way. 2.
By module. exports, we can export functions, objects, and their references from one file and can use them in other files by importing them by require() method.
Every module can have two different types of export, named export and default export.
TL;DR: JavaScript modules are loaded in different environments (different module loading systems, or no proper module system at all). The code you have is some boiler-plate code that lets you load a module in these different environments correctly, in a clean way.
In more detail: the actual definition you give is a "factory function": a function that returns the module contents when evaluated. A factory function is a very flexible thing that can be used in a variety of ways.
This is essentially your third example. Here, the factory function is executed immediately, and assigned to a global variable:
var MyModule = (function () {
// this is the factory function
})(); // execute immediately
The result is that other modules can reference this module by using the global variable - but this means you have to be careful to load all the modules in the correct order.
Asynchronous Module Definition syntax is a pretty simple syntax, which provides a function called define()
(spec here). This lets you describe modules by providing their dependencies and the factory function:
define('module-name', ['dep1', 'dep2'], function (dep1, dep2) {
...
});
So here, module-name
is defined, but the factory function will only be executed when all the dependencies are loaded - this means that you can load the module definitions in any order, and the module loader is responsible for executing them all properly.
In CommonJS environments (such as Node.js, which runs in the command line or on a server), there is a global(-ish) object called module
. Whatever you assign to module.exports
is considered to be the value of the module.
If you want to use this with a factory function, it's pretty similar to the browser globals scenario, just that you assign it to module.exports
:
module.exports = (function () {
// this is the factory function
})(); // execute immediately
It's possible to detect which module loaders are available by inspecting the environment (e.g. typeof define
and typeof module
).
The code block at the top detects which module loader is available and uses the factory function with AMD, CommonJS or browser globals, depending which is available.
While you could in theory do this inline in your code, separating it out to the top is nice and neat.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With