Immediately Invoked Function Expressions

Back at the writing board, after a while. Lots of changes happened in my personal life, putting off writing this important article for a while. This is a must have addendum for the article series I started on JavaScript.

We know that everything in JavaScript can be treated as objects. Objects doesn’t necessarily need to have a name all the time, especially we only want to that specific object to do one thing and just go away. This is not a specific thing to JavaScript as you may all know. We have anonymous functions or classes mostly, in languages like Java or C# too, exactly used for the same reason I talked about. But in JavaScript this is a pivotal concept because there can be some misunderstanding and confusions around the whole thing, as JS is loosely typed. These anonymous functions are called Immediately Invoked function expressions (IIFE).

If you just read its purpose as in the previous paragraph, it doesn’t seem like there’s a lot more to it right? This is why I was surprised also, when I went over the whole concept in this very thorough article. Through this article I learned a lot on some fundamentals on Javascript it self, through the analysis from the name of IIFE through its function.

Some devs don’t put much attention to terminology at all. But with proper terminology, comprehension and communication of concepts in any subject matter unravels tremendously. That’s why it’s important to narrow down on the semantics of IIFE as well as anything. Because its claimed that IIFEs are called other things as well, like “self-executing anonymous functions”. On first glance they seem to give the same meaning. But it really isn’t. The original article goes more in depth as to why the second term is wrong.

As a special feature of functions as a Object in JavaScript, functions when invoked create their own scope, an execution context, which is a like a private space owned by that function object only. This is a concept we discussed in one of the previous articles. Invocation of a function is a way to encapsulate, a way to create privacy.

 
function makeCounter() {

    // i is a private variable, only accessible inside makeCounter
    var i = 0;
    return function () {
        console.log(i++);
    };
}

The function we return from invoking makeCounter is accessible outside of the scope of makeCounter. But since its accessing the private variable ‘i’ and showing its value to the outside, its a privileged member of makeCounter.

Now lets invoke makeCounter twice for two instances. Note that `counter` and `counter2` each have their own scoped `i`.


var counter = makeCounter();
counter(); // logs: 1
counter(); // logs: 2

var counter2 = makeCounter();
counter2(); // logs: 1
counter2(); // logs: 2

That’s not so hard was it. Calling makeCounter creates their own personal spaces. And the variable is not accessible outside of those spaces.


i; // ReferenceError: i is not defined (it only exists inside makeCounter)

There are several ways we can define a function in Javascript :


function foo1() {}
var foo2 = function() {}

Both foo1 and foo2 are invoked by adding () to the end, you know, coz they are functions. So foo1 and foo2 is just basically names that we gave for this code : function () { /* executed code with the function */ } . And that can be invoked by just adding () to the end. So it stands to reason that we can just drop the different name calling and just do this :

function () { /* executed code with the function */ } ()

But try it, it just doesn’t work like that, it says that it’s a syntax error at ‘(‘. So what’s the deal with that? This is because of the great old lady who only knows what its reading at the moment and nothing beyond that, the JavaScript parser. When the parser sees the keyword function like above, it starts to think, ah this is a start of a function declaration. NOT a function expression as we expect it to be. A function declaration is a statement that we are declaring this function to the scope and that is all. So as a statement, the parser expects the function to have a name and because it doesn’t see a name before the ‘(‘ it throws an error. So we must have a way of telling the parser ‘hey lady, this is not a statement, treat this as a expression will ya’ before she throws a tantrum. So how do we do that? That’s where IIFE concept comes in.

Before going into that, let’s look in to this whole parenthesis business again shall we. So the problem we have is we didn’t have a name for our function declaration right. Fine so we add a name, like in the case of foo1 above and try to invoke it by adding parenthesis at the end :


function foo1 () {} ()

Again this fails, but for a totally different reason. Even if we try to invoke ‘foo1’ by adding parenthesis to the end , the parser doesn’t want to treat it as an expression still. It’s still a function statement, which ends with the }. Remember we can invoke function expressions, Function declarations cannot be invoked. Any other parenthesis we add after the function declaration is the start of something new. In this case the parenthesis is parsed as a way to scope context and since it doesn’t have anything in it, the parser throws the error. We can have any expression inside parenthesis like this. That’s why this code works :


function foo1 () {} (1)

Which is equivalent to :

function foo1 () {} 

(1);

Now solving that syntax error and introducing IIFE is riding on this parenthesis thing. As we said we can have any expression inside a parenthesis when its used to scope context as in the above example. Any expression, but not statements. So if we have our function expression without a name inside parenthesis then the parser knows that it’s an expression and will not treat it as a statement when it encounters the function keyword.

So intuitively we can think of two ways now to introduce IIFEs :


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

Both works ok. The whole point of using the parenthesis was to tell the parser to expect a function expression here. When a function expression is automatically expected in some cases, we can drop the extra parenthesis. Like in the below examples :


var i = function(){ /* code */ }();
true && function(){ /* code */ }();
0, function(){ /* code */ }()

Or these, although slightly harder to read, also works, because they are all function expressions because of the unary operators.


!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

And this also. Only needs the extra parenthesis if we pass an argument.

new function(){ /* code */ };
new function(i) { /*code */ } (3);

But as a rule of thumb it is generally better to use the extra parenthesis surrounding the function expression as a convention. It disambiguates between returning the invoked result of the expression as opposed to returning the expression it self when reading the code. Especially when the expression is really long, the reader doesn’t have to go to the end of the expression to see if its invoked when its surrounded with parenthesis.

So that’s the deal with IIFEs. Which basically creates a private execution context where we can do stuff and not affect the global scope. Let’s see how this deals with closures. I intend to add an article on closures. For now, This page will shed some light on the area.

Just like in named functions, we can pass in arguments to IIFEs. With the principle of closures, the IIFE has access to the outer scopes variables, and since the IIFE is private, we can lock in outer scopes variables.

Let’s look at the example to understand this concept. This code block gets every anchor tag in the page and overrides its click event to console log its index according to every anchor tag in the page. At least that’s what its supposed to do :


var elems = document.getElementsByTagName( 'a' );

for ( var i = 0; i < elems.length; i++ ) {
    elems[ i ].addEventListener( 'click', function(e){
        e.preventDefault();
        alert( 'I am link #' + i );
    }, 'false' );
}

That function we pass as the second argument of addEventListener is an anonymous function it self, but it’s not invoked. It will be only invoked when we click the a tag. But when that happens the loop is already executed, and the value of i is the total number of a tags in the page. So whenever we click an ‘a’ it will just show the same value : ‘I am link #‘ , i being the same every time. That’s not what we want. This is because we only assign the function to the click even , but the value of i when the assignment happens is never locked in with the function. So when executing the click event, it looks for the i declared before, and used that. So we need to lock in the value of i privately for each click event execution. IIFE to the rescue.


var elems = document.getElementsByTagName( 'a' );

for ( var i = 0; i < elems.length; i++ ) {

    (function( lockedInIndex ){
        elems[ i ].addEventListener( 'click', function(e){
            e.preventDefault();
            alert( 'I am link #' + lockedInIndex );
        }, 'false' );
    })( i );
}

Here for each iteration of the loop, we do what we did before inside an IIFE. When invoking we pass in the i of the iteration, And i is used inside to assign the click event function, and since i is used in the invocation of the IIFE it’s value is locked in. So when the click event occurs, it doesn’t have to look for an outer i. Each of those click functions have its own click function assigned with the right value of i.

There’s another way to do it, by using an IIFE when assgning the click event, like this :


var elems = document.getElementsByTagName( 'a' );

for ( var i = 0; i < elems.length; i++ ) {

    elems[ i ].addEventListener( 'click', (function( lockedInIndex ){
        return function(e){
            e.preventDefault();
            alert( 'I am link #' + lockedInIndex );
        };
    })( i ), 'false' );

}

Here, the second argument is an IIFE where we invoke at the time of the addEventListener call, so that the IIFE returns the function which needs to be executed when clicked with the locked in index. Both methods are equally valid, made easy by IIFEs.

Another great advantage of using this IIFE, is it doesn’t pollute the global scope. You must realize that we could’ve just done this by introducing another function just to do this and invoking that inside the loop. But it’s totally unnecessary and would be just a pollution of the scope.

So we discussed about the Module pattern. In the module pattern we basically return an object instead of a function as we did in the first example of this article (the makeCounter one). Now we can use an IIFE in place of the makeCounter function, so that we don’t need to declare the makeCounter function as we did before. By doing so we are using IIFE in making a module.


var counter = (function(){
var i = 0;

return {
    get: function(){
        return i;
    },
    set: function( val ){
        i = val;
    },
    increment: function() {
        return ++i;
    }
};
}());

Actually there’s nothing special here instead of dropping the middleman and just using an IIFE to create our module. But if we need another counter it’s probably best to use a named method instead of the repetition.

So yeah, that’s the gist of IIFEs. They are incredibly useful whenever we need to encapsulate data in execution contexts.

Summary :

  • Immediately Invoked Function Expressions are functions which we invoke at the time of declaration, so that it does a thing and never be used again.
  • Some call it Self-Executing anonymous functions, which can be misleading as the function doesn’t execute or invoke it self, like a recurring function.
  • Functions, when invoked, create their own execution context, a private scope, which can be used in encapsulation.
  • There are different ways to define a names function in JS.
  • The JavaScript parser treats function declarations and statements differently.
    Inside parentheses in a globale scope, we can only have expressions and not statements. So use that to create IIFE.
  • With decreased readability we can drop the surrounding parenthesis in some cases when using IIFEs.
  • Using IIFE in combination with closures is necessary when we need to encapsulate values inside function objects.
  • IIFE helps to keep the global context clean.
  • IIFE can be used in the module pattern, when we want to create a singleton module.

 

 

Advertisements
This entry was posted in Design Patterns, Javascript and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s