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?
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:
It's usually to namespace (see later) and control the visibility of member functions and/or variables. Think of it like an object definition. jQuery plugins are usually written like this.
In Javascript, you can nest functions. So, the following is legal:
Now you can call
outerFunction()
, but the visiblity ofinnerFunction()
is limited to the scope ofouterFunction()
, meaning it is private toouterFunction()
. It basically follows the same principle as variables in Javascript:Correspondingly:
In the above scenario, you can call
globalFunction()
from anywhere, but you cannot calllocalFunction1
orlocalFunction2
.What you're doing when you write
(function() { ... code ... })()
, is you're making the code inside a function literal (meaning the whole "object" is actually a function). After that, you're self-invoking the function (the final()
). So the major advantage of this as I mentioned before, is that you can have private methods/functions and properties:In the first example, globalFunction() was the public function that could be called to access the public functionality, but in the above example how do you call it? Here the self-invoking function makes the code automatically run at start up. Just like you can add initMyStuff(); to the top of any .js file and it will automatically run as part of the global scope, this self-invoking function will also automatically run, although since it's an unnamed function it cannot be called multiple times like initMyStuff() could be.
The neat thing is that you can also define things inside and expose it to the outside world so (an example of namespacing so you can basically create your own library/plugin):
Now you can call
myPlugin.public_function1()
, but you cannot accessprivate_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 injQuery
or$
like so: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 calledjQuery
, 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:Earlier I described how these functions run automatically at startup, but if they run automatically who is passing in the arguments? This technique assumes all the parameters are defined as global variables. So if jQuery wasn't defined as a global variable this example would not work, and could not be called any other way since our example is an anonymous function. As you might guess, one things jquery.js does during it's initialization is define a 'jQuery' global variable, as well as it's more famous '$' global variable, which allows this code to work after jquery.js is included.
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
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.
In short
Summary
In its simplest form, this technique aims to wrap code inside a function scope.
It helps decreases chances of:
It does not detect when the document is ready - it is not some kind of
document.onload
norwindow.onload
It is commonly known as an
Immediately Invoked Function Expression (IIFE)
orSelf Executing Anonymous Function
.Code Explained
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:
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:
So our more complex example becomes:
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:
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:or
or
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
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?"
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 dowindow.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:
block scope
(Update: block scope local variables added in ES6.)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 themodule pattern
, which is commonly done by leveraging this IIFE pattern. Have fun :)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.