Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export module pattern

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;
}());
like image 781
Ahmad Milzam Avatar asked Nov 25 '14 18:11

Ahmad Milzam


People also ask

What are module exports?

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.

What is the difference between exports and module exports?

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.

What can you export with module exports?

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.

What are the two types of module exports in JavaScript?

Every module can have two different types of export, named export and default export.


1 Answers

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.

Browser globals

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 Definitions

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.

CommonJS

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

Option (d): All of the above

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.

like image 113
cloudfeet Avatar answered Sep 20 '22 02:09

cloudfeet