Init function in javascript and how it works
I often see the following code:
(function () {
// init part
})();
but I never could get my head around how it works. I find the last brackets especially confusing. Could someone explain how it works in terms of Execution Contexts (EC) and Variable Objects (VO)?
The way I usually explain this to people is to show how it's similar to other JavaScript patterns.
First, you should know that there are two ways to declare a function (actually, there's at least five, but these are the two main culprits):
function foo() {/*code*/}
and
var foo = function() {/*code*/};
Even if this construction looks strange, you probably use it all the time when attaching events:
window.onload=function(){/*code*/};
You should notice that the second form is not much different from a regular variable declaration:
var bar = 5;
var baz = 'some string';
var foo = function() {/*code*/};
But in JavaScript, you always have the choice between using a value directly or through a variable. If bar
is 5
, then the next two statements are equivalent:
var myVal = bar * 100; // use 'bar'
var myVal = 5 * 100; // don't use 'bar'
Well, if you can use 5
on its own, why can't you use function() {\*code*\}
on its own too? In fact, you can. And that's called an anonymous function. So these two examples are equivalent as well:
var foo = function() {/*code*/}; // use 'foo'
foo();
(function(){/*code*/})(); // don't use 'foo'
The only difference you should see is in the extra brackets. That's simply because if you start a line with the keyword function
, the parser will think you are declaring a function using the very first pattern at the top of this answer and throw a syntax error exception. So wrap your entire anonymous function inside a pair of braces and the problem goes away.
In other words, the following three statements are valid:
5; // pointless and stupid
'some string'; // pointless and stupid
(function(){/*code*/})(); // wonderfully powerful
[EDIT in 2020]
The previous version of my answer recommended Douglas Crockford's form of parens-wrapping for these "immediately invoked anonymous functions". User @RayLoveless recommended in 2012 to use the version shown now. Back then, before ES6 and arrow functions, there was no obvious idiomatic difference; you simply had to prevent the statement starting with the function
keyword. In fact, there were lots of ways to do that. But using parens, these two statements were syntactically and idiomatically equivalent:
( function() { /* code */}() );
( function() { /* code */} )();
But user @zentechinc's comment below reminds me that arrow functions change all this. So now only one of these statements is correct.
( () => { /* code */ }() ); // Syntax error
( () => { /* code */ } )();
Why on earth does this matter? Actually, it's pretty easy to demonstrate. Remember an arrow function can come in two basic forms:
() => { return 5; }; // With a function body
() => { console.log(5); };
() => 5; // Or with a single expression
() => console.log(5);
Without parens wrapping this second type of arrow function, you end up with an idiomatic mess:
() => 5(); // How do you invoke a 5?
() => console.log(5)(); // console.log does not return a function!
That pattern will create a new execution context (EC) in which any local variable objects (VO's) will live, and will likewise die when the EC exits. The only exception to this lifetime is for VO's which become part of a closure.
Please note that JavaScript has no magic "init" function. You might associate this pattern with such since most any self-respecting JS library (jQuery, YUI, etc.) will do this so that they don't pollute the global NS more than they need to.
A demonstration:
var x = 1; // global VO
(function(){
var x = 2; // local VO
})();
x == 1; // global VO, unchanged by the local VO
The 2nd set of "brackets" (those are actually called parens, or a set of parentheses), are simply to invoke the function expression directly preceding it (as defined by the prior set of parenthesis).
The code creates an anonymous function, and then immediately runs it. Similar to:
var temp = function() {
// init part
}
temp();
The purpose of this construction is to create a scope for the code inside the function. You can declare varaibles and functions inside the scope, and those will be local to that scope. That way they don't clutter up the global scope, which minimizes the risk for conflicts with other scripts.