What is the purpose of wrapping whole Javascript files in anonymous functions like “(function(){ … })()”?
Asked Answered
I

10

644

I have been reading a lot of Javascript lately and I have been noticing that the whole file is wrapped like the following in the .js files to be imported.

(function() {
    ... 
    code
    ...
})();

What is the reason for doing this rather than a simple set of constructor functions?

Isochor answered 11/3, 2010 at 1:20 Comment(3)
Since I imagine this will be used by a lot of people, please don't forget the closing ;Asare
This technic is called "IIFE" I think. This stands for Immediately Invoked Function Expression en.wikipedia.org/wiki/Immediately-invoked_function_expressionCarpentaria
possible duplicate of What is the purpose of a self executing function in javascript?Aglimmer
C
851

It's usually to namespace (see later) and control the visibility of member functions and/or variables. Think of it like an object definition. The technical name for it is an Immediately Invoked Function Expression (IIFE). jQuery plugins are usually written like this.

In Javascript, you can nest functions. So, the following is legal:

function outerFunction() {
   function innerFunction() {
      // code
   }
}

Now you can call outerFunction(), but the visiblity of innerFunction() is limited to the scope of outerFunction(), meaning it is private to outerFunction(). It basically follows the same principle as variables in Javascript:

var globalVariable;

function someFunction() {
   var localVariable;
}

Correspondingly:

function globalFunction() {
  
   var localFunction1 = function() {
       //I'm anonymous! But localFunction1 is a reference to me!
   };

   function localFunction2() {
      //I'm named!
   }
}

In the above scenario, you can call globalFunction() from anywhere, but you cannot call localFunction1 or localFunction2.

What you're doing when you write (function() { ... })(), is you're making the code inside the first set of parentheses a function literal (meaning the whole "object" is actually a function). After that, you're self-invoking the function (the final ()) that you just defined. So the major advantage of this as I mentioned before, is that you can have private methods/functions and properties:

(function() {
   var private_var;

   function private_function() {
     //code
   }
})();

In the first example, you would explicitly invoke globalFunction by name to run it. That is, you would just do globalFunction() to run it. But in the above example, you're not just defining a function; you're defining and invoking it in one go. This means that when your JavaScript file is loaded, it is immediately executed. Of course, you could do:

function globalFunction() {
    // code
}
globalFunction();

The behavior would largely be the same except for one significant difference: you avoid polluting the global scope when you use an IIFE (as a consequence it also means that you cannot invoke the function multiple times since it doesn't have a name, but since this function is only meant to be executed once, it really isn't an issue).

The neat thing with IIFEs is that you can also define things inside and only expose the parts that you want to the outside world so (an example of namespacing so you can basically create your own library/plugin):

var myPlugin = (function() {
 var private_var;

 function private_function() {
 }

 return {
    public_function1: function() {
    },
    public_function2: function() {
    }
 }
})()

Now you can call myPlugin.public_function1(), but you cannot access private_function()! So pretty similar to a class definition. To understand this better, I recommend the following links for some further reading:

EDIT

I forgot to mention. In that final (), you can pass anything you want inside. For example, when you create jQuery plugins, you pass in jQuery or $ like so:

(function(jQ) { ... code ... })(jQuery) 

So what you're doing here is defining a function that takes in one parameter (called jQ, a local variable, and known only to that function). Then you're self-invoking the function and passing in a parameter (also called jQuery, but this one is from the outside world and a reference to the actual jQuery itself). There is no pressing need to do this, but there are some advantages:

  • You can redefine a global parameter and give it a name that makes sense in the local scope.
  • There is a slight performance advantage since it is faster to look things up in the local scope instead of having to walk up the scope chain into the global scope.
  • There are benefits for compression (minification).

Earlier I described how these functions run automatically at startup, but if they run automatically who is passing in the arguments? This technique assumes that all the parameters you need are already defined as global variables. So if jQuery wasn't already defined as a global variable this example would not work. As you might guess, one thing jquery.js does during its initialization is define a 'jQuery' global variable, as well as its more famous '$' global variable, which allows this code to work after jQuery has been included.

Cuisse answered 11/3, 2010 at 1:32 Comment(8)
Very cool, I understand namespace well, but I've seen a lot of that last example of yours and couldn't figure out what people were trying to achieve. This really clears things up.Isochor
I think adding a leading and trailing semicolon ';' would make the example complete - ;(function(jQ) { ... code ... })(jQuery); This way if someone left off a semicolon in their script it would not break yours, especially if you plan to minify and concatenate your script with other.Oat
nice post, I like the emphasis on private variables. I also like the opening on the module-pattern/closures (public_function1 & public_function2) & how you pass variables, even though slightly getting out of scope it's a nice introduction. I also added an answer, this one focussing on what I suppose are the roots of the syntax & differences between function statement vs function expression & what I think is "just a convention" vs "the only way to achieve this result".Carpentaria
Great post, I think maybe more on how passing variables into the self executing function is beneficial. The context in the self executing function is clean - no data. You can pass in the context by doing this (function (context) { ..... })(this) which then allows you to attach anything you like to the parent context thus exposing it.Zorn
Great post! I'd like to add that it is also common on this environment to have an export declaration at the end of the code (sometimes it is the only executable part of this anonymous function definition). So most libraries end with an export declaration of the type this.myLib = myLib, define(myLib), module.exports = myLib or a combination of these.Lighterman
First link is deadArgeliaargent
Great answer. Good note about returning publics, that's a nice explicit easy way to do that and have all public defs in one spot. But, it's worth noting you can also just use "this.somePublicFunction = function(){};" and also achieve the same thing without needing any return function, or just a "return this" if you want to return the main object with all it's "this." functions already attached in this public way.Neume
Great post, but I'd like to add that since module is introduced in ES6, you almost never needed IIFE anymore: github.com/airbnb/javascript/blob/master/…Thermoscope
C
82

In short

Summary

In its simplest form, this technique aims to wrap code inside a function scope.

It helps decreases chances of:

  • clashing with other applications/libraries
  • polluting superior (global most likely) scope

It does not detect when the document is ready - it is not some kind of document.onload nor window.onload

It is commonly known as an Immediately Invoked Function Expression (IIFE) or Self Executing Anonymous Function.

Code Explained

var someFunction = function(){ console.log('wagwan!'); };

(function() {                   /* function scope starts here */
  console.log('start of IIFE');

  var myNumber = 4;             /* number variable declaration */
  var myFunction = function(){  /* function variable declaration */
    console.log('formidable!'); 
  };
  var myObject = {              /* object variable declaration */
    anotherNumber : 1001, 
    anotherFunc : function(){ console.log('formidable!'); }
  };
  console.log('end of IIFE');
})();                           /* function scope ends */

someFunction();            // reachable, hence works: see in the console
myFunction();              // unreachable, will throw an error, see in the console
myObject.anotherFunc();    // unreachable, will throw an error, see in the console

In the example above, any variable defined in the function (i.e. declared using var) will be "private" and accessible within the function scope ONLY (as Vivin Paliath puts it). In other words, these variables are not visible/reachable outside the function. See live demo.

Javascript has function scoping. "Parameters and variables defined in a function are not visible outside of the function, and that a variable defined anywhere within a function is visible everywhere within the function." (from "Javascript: The Good Parts").


More details

Alternative Code

In the end, the code posted before could also be done as follows:

var someFunction = function(){ console.log('wagwan!'); };

var myMainFunction = function() {
  console.log('start of IIFE');

  var myNumber = 4;
  var myFunction = function(){ console.log('formidable!'); };
  var myObject = { 
    anotherNumber : 1001, 
    anotherFunc : function(){ console.log('formidable!'); }
  };
  console.log('end of IIFE');
};

myMainFunction();          // I CALL "myMainFunction" FUNCTION HERE
someFunction();            // reachable, hence works: see in the console
myFunction();              // unreachable, will throw an error, see in the console
myObject.anotherFunc();    // unreachable, will throw an error, see in the console

See live demo.


The Roots

Iteration 1

One day, someone probably thought "there must be a way to avoid naming 'myMainFunction', since all we want is to execute it immediately."

If you go back to the basics, you find out that:

  • expression: something evaluating to a value. i.e. 3+11/x
  • statement: line(s) of code doing something BUT it does not evaluate to a value. i.e. if(){}

Similarly, function expressions evaluate to a value. And one consequence (I assume?) is that they can be immediately invoked:

 var italianSayinSomething = function(){ console.log('mamamia!'); }();

So our more complex example becomes:

var someFunction = function(){ console.log('wagwan!'); };

var myMainFunction = function() {
  console.log('start of IIFE');

  var myNumber = 4;
  var myFunction = function(){ console.log('formidable!'); };
  var myObject = { 
    anotherNumber : 1001, 
    anotherFunc : function(){ console.log('formidable!'); }
  };
  console.log('end of IIFE');
}();

someFunction();            // reachable, hence works: see in the console
myFunction();              // unreachable, will throw an error, see in the console
myObject.anotherFunc();    // unreachable, will throw an error, see in the console

See live demo.

Iteration 2

The next step is the thought "why have var myMainFunction = if we don't even use it!?".

The answer is simple: try removing this, such as below:

 function(){ console.log('mamamia!'); }();

See live demo.

It won't work because "function declarations are not invokable".

The trick is that by removing var myMainFunction = we transformed the function expression into a function declaration. See the links in "Resources" for more details on this.

The next question is "why can't I keep it as a function expression with something other than var myMainFunction =?

The answer is "you can", and there are actually many ways you could do this: adding a +, a !, a -, or maybe wrapping in a pair of parenthesis (as it's now done by convention), and more I believe. As example:

 (function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.

or

 +function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console

or

 -function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console

So once the relevant modification is added to what was once our "Alternative Code", we return to the exact same code as the one used in the "Code Explained" example

var someFunction = function(){ console.log('wagwan!'); };

(function() {
  console.log('start of IIFE');

  var myNumber = 4;
  var myFunction = function(){ console.log('formidable!'); };
  var myObject = { 
    anotherNumber : 1001, 
    anotherFunc : function(){ console.log('formidable!'); }
  };
  console.log('end of IIFE');
})();

someFunction();            // reachable, hence works: see in the console
myFunction();              // unreachable, will throw an error, see in the console
myObject.anotherFunc();    // unreachable, will throw an error, see in the console

Read more about Expressions vs Statements:


Demystifying Scopes

One thing one might wonder is "what happens when you do NOT define the variable 'properly' inside the function -- i.e. do a simple assignment instead?"

(function() {
  var myNumber = 4;             /* number variable declaration */
  var myFunction = function(){  /* function variable declaration */
    console.log('formidable!'); 
  };
  var myObject = {              /* object variable declaration */
    anotherNumber : 1001, 
    anotherFunc : function(){ console.log('formidable!'); }
  };
  myOtherFunction = function(){  /* oops, an assignment instead of a declaration */
    console.log('haha. got ya!');
  };
})();
myOtherFunction();         // reachable, hence works: see in the console
window.myOtherFunction();  // works in the browser, myOtherFunction is then in the global scope
myFunction();              // unreachable, will throw an error, see in the console

See live demo.

Basically, if a variable that was not declared in its current scope is assigned a value, then "a look up the scope chain occurs until it finds the variable or hits the global scope (at which point it will create it)".

When in a browser environment (vs a server environment like nodejs) the global scope is defined by the window object. Hence we can do window.myOtherFunction().

My "Good practices" tip on this topic is to always use var when defining anything: whether it's a number, object or function, & even when in the global scope. This makes the code much simpler.

Note:

  • javascript does not have block scope (Update: block scope local variables added in ES6.)
  • javascript has only function scope & global scope (window scope in a browser environment)

Read more about Javascript Scopes:


Resources


Next Steps

Once you get this IIFE concept, it leads to the module pattern, which is commonly done by leveraging this IIFE pattern. Have fun :)

Carpentaria answered 4/11, 2014 at 15:31 Comment(3)
Very helpful. Thanks a lot!Doctorate
Nice, I prefer the demo version :)Mafalda
Such a great explanation. Thank you!Postulant
E
27

Javascript in a browser only really has a couple of effective scopes: function scope and global scope.

If a variable isn't in function scope, it's in global scope. And global variables are generally bad, so this is a construct to keep a library's variables to itself.

Ed answered 11/3, 2010 at 1:25 Comment(4)
But doesn't the constructor function itself provides scope for its own variables?Isochor
Yes, each function defined in this library could define its own local variables, but this allows variables to be shared between the functions without them leaking outside of the libraryEd
@Gareth, so this allows for "global" variables within a scope (;Dade
@FranciscoPresencia "global within a scope" isn't a useful phrase, because that's basically just what "scope" means. The whole point of the "global" scope is that it's specifically the scope that all other scopes have access to.Ed
E
20

That's called a closure. It basically seals the code inside the function so that other libraries don't interfere with it. It's similar to creating a namespace in compiled languages.

Example. Suppose I write:

(function() {

    var x = 2;

    // do stuff with x

})();

Now other libraries cannot access the variable x I created to use in my library.

Emulate answered 11/3, 2010 at 1:25 Comment(5)
Careful with your terminology. Namespacing implies that the variables can be accessed from outside by addressing the namespace (typically by using a prefix). While this is possible in Javascript that isn't what's demonstrated hereEd
I agree it is not exactly like a namespace, however, you can provide similar functionality by returning an object with properties which you want to publicize: (function(){ ... return { publicProp1: 'blah' }; })();. Obviously not perfectly parallel to namespacing, but it may help to think of it that way.Emulate
in your example x is still a private variable... Despite you wrapping it in a IIFE. go ahead and try to access x outside of the function, you can't..Jaquenette
Your point is not valid. Even in the following function other libraries can't access x. function() { var x = 2 }Jaquenette
@Jaquenette I agree. I do not contradict that assertion. In fact, I made the same assertion as the last sentence of this answer.Emulate
A
8

You can use function closures as data in larger expressions as well, as in this method of determining browser support for some of the html5 objects.

   navigator.html5={
     canvas: (function(){
      var dc= document.createElement('canvas');
      if(!dc.getContext) return 0;
      var c= dc.getContext('2d');
      return typeof c.fillText== 'function'? 2: 1;
     })(),
     localStorage: (function(){
      return !!window.localStorage;
     })(),
     webworkers: (function(){
      return !!window.Worker;
     })(),
     offline: (function(){
      return !!window.applicationCache;
     })()
    }
Auntie answered 11/3, 2010 at 2:59 Comment(2)
What does the !! do?Nares
!! converts a value to it's boolean (true/false) representation.Sesquiplane
L
7

In addition to keeping the variables local, one very handy use is when writing a library using a global variable, you can give it a shorter variable name to use within the library. It's often used in writing jQuery plugins, since jQuery allows you to disable the $ variable pointing to jQuery, using jQuery.noConflict(). In case it is disabled, your code can still use $ and not break if you just do:

(function($) { ...code...})(jQuery);
Leadsman answered 11/3, 2010 at 1:33 Comment(0)
T
3
  1. To avoid clash with other methods/libraries in the same window,
  2. Avoid Global scope, make it local scope,
  3. To make debugging faster (local scope),
  4. JavaScript has function scope only, so it will help in compilation of codes as well.
Tc answered 26/10, 2016 at 18:52 Comment(0)
Q
1

We should also use 'use strict' in the scope function to make sure that the code should be executed in "strict mode". Sample code shown below

(function() {
    'use strict';

    //Your code from here
})();
Quadrature answered 24/11, 2015 at 6:37 Comment(5)
Why should we use strict?Eunuchize
Check this article: #1336351Quadrature
Does not really answer the question!Glance
Pritam, its a good practice use. Please do proper research before voting down any answerQuadrature
'use strict' saves bad programmers from themselves. And since the majority of programmers are bad programmers, it helps prevent them from doing things they definitely should not be doing and ending up in a quickly sinking mess of code.Barram
A
0

Provide an example for the accepted answer, from https://requirejs.org/docs/whyamd.html:

(function () {
    var $ = this.jQuery;

    this.myExample = function () {};
}());

The code demonstrates that we can:

  1. use global variables inside the scope
  2. export functions, variables etc.. by binding on this, which is the window object as for browsers.
Adest answered 18/2, 2022 at 10:51 Comment(0)
L
0

Its called encapsulation in OOP.

Longmire answered 30/6, 2022 at 7:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.