3

I read some JS module design patterns recently. I came across this small code snippet as below.

(function(window) {
    var Module = {
        data: "I'm happy now!"
    };

    window.Module = Module;
})(window);

Still not quite understand this code well, my questions are:

  • How to use/call this module outside this particluar JS file? Need I assign a variable to this module? e.g. var module1 = (...)(...);
  • Could anyone explain what the window parameter here stands for?
  • Is it a good practice to have two/three such kind of modules in the same file?
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
catlovespurple
  • 682
  • 1
  • 7
  • 20

2 Answers2

9

The main reason to create an anonymous function in this case is to prevent global object pollution. It's not really a module pattern.

The problem arise when you declare a variable. Without the function scope, the variable will be added to the global object (window). If you were to declare the variables within a function. It would add the variable to the function scope without polluting the global object window.

What happen is that a javascript file could add a variable named foo and on a different file use that variable named foo too. Unless you really want to have a variable shared by two javascript files, it would probably create conflicts and bug that are difficult to fix.

For example: a.js

var foo = "one"

b.js

var foo = "two"

c.js

alert(foo)

In this case, the alert box might show either "one" or "two", depending of the order in the javascript files are included.

But having this a.js:

(function () {
    var foo = "one"
})()

b.js

(function () {
    var foo = "two"
})()

c.js

(function () {
    alert(foo)
})()

This would create an error as you cannot alert a non declared variable.

One way to detect undefined variables, is to make sure to execute the javascript code in strict mode.

To do that, add the string "use strict" at the top of the file or function.

function () {
  "use strict"
  ...
}

Undeclared variable will raise errors and it should be possible to fix the code that way.

Also, if you forget to declare a variable with the var keyword, it might end up adding the variable to the global scope even if the code is scoped into a function. The only way to prevent global scope pollution is to run the code in strict mode.

In the code snippet that you provided, the module with name Module is explicitly added to the window object. You can access the window object from any place in javascript unless the window name is ghosted by an other variable.

Now, back to the modules. If you want to define modules, it can be done in many ways. As an exemple, you could create an object on the window object called modules. In this object, you'll insert your modules.

module.js

window.modules = {}

foo.js

(function (window) {
  var module = {}
  ...
  window.modules.foo = module
})(window)

This variant isn't super good as you have to manually add the module to the modules object. You have to manually modify the window object, and that can be subject to errors.

modules.js

window.modules = {}

function define(name, constructor) {
  var module = {exports: {}}
  constructor(module)
  window.modules[name] = module.exports
}

function require(name) {
  return window.modules[name]
}

foo.js

define("foo", function (module) {
  module.exports.one = function () {
    return 1
  }

  module.exports.plus = function (a, b) {
    return a + b
  }
})

bar.js

define("bar", function (module) {
  module.exports = function () {
    var foo = require("foo")
    return foo.plus(foo.one(), foo.one())
  }
})

This is a module definition that looks a bit like module defined with http://requirejs.org/. It is quite basic as it doesn't take into account module dependencies so if bar is loaded and used before foo. Then the require method won't be able to return the module.

Also, if you want to store modules without having them visible into the global scope, you can only define the require and define method on the window object and hide modules into an anonymous scope like this:

  (function (window) {
    var modules = {}

    function define(name, constructor) {
      var module = {exports: {}}
      constructor(module)
      modules[name] = module.exports
    }

    function require(name) {
      return modules[name]
    }

    window.define = define
    window.require = require
  })(window)

This way, define and require are the only function that can give you access to modules. Other modules won't be able to modify other modules without requiring them first. This can be useful when using third parties script that could conflict with your module system.

Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
1

In fact this is not a module, but a Self-Invoking Ananymous function or an Immediate function which gets an object in parameter and assign a Module property to it:

  • The page window is a parameter passed to this function.

  • So an object named Module containing a data property is assigned to window.

JavaScript Self-Invoking Functions:

A self-invoking expression is invoked (started) automatically, without being called.

Function expressions will execute automatically if the expression is followed by ().

You cannot self-invoke a function declaration.

You have to add parentheses around the function to indicate that it is a function expression

So As you can see Immediate Functions can't be called as its name states it will be immediately executed and by its self, no other function or scope can execute it.

For better reference take a look at :


And concerning your last question about its benefits and good practices as shown on the given Article reference:

Where to use self-executing functions?

One obvious situation is when you want to auto-run a function like I showed in above example but that is trivial. If you are in a situation where you want to run a piece of code repeatedly like updating something in the database based on user interaction or fetching records from database every 10 seconds or you want to load new stories via ajax similar to how facebook does on its homepage or some other similar situation, one would normally go for setInterval function something like this:

setInterval(doStuff, 10000);

Above, doStuff function will get called every 10 seconds. That is the normal approach most developers seem to go with. However, there is a huge problem with that.

The setInterval will call doStuff function exactly at specified time of 10 seconds again and again irrespective of whether doStuff function actually finished doing what it is supposed to do. That is bad and will certainly get you into unexpected results.

That is one example of where setInterval is "bad" and should be avoided.

This is exactly where self-executing functions come in handy. We can do the same task with the help of self-executing function along with setTimeout like this:

function foo(){
     // your other code here  
     setTimeout(foo, 10000);
}();

This code will also repeat itself again and again with one difference. setTimeout will never get triggered unless doStuff is finished. A much better approach than using setInterval in this situation.

Calling it from another file:

And if this function is on another file it will be called automatically if this file is included.

Why do we use Self-Invoking Functions in JavaScript?

And if you ask yourself why do we use these functions, self-invoked function are used to manage Variable Scope.

Take a look at the answer here for further information.

Community
  • 1
  • 1
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
  • Thanks chsdk! Can you please also show me how to use this anonymous function outside this JS file? – catlovespurple Aug 19 '15 at 16:23
  • @catlovespurple Take a look at my Edited answer you will find all the explanation you are looking for and all the answers to your questions. – cнŝdk Aug 20 '15 at 12:20