About (Function(){ ... }()) and callThis()

Asked

Viewed 975 times

14

Coffeescript compiles your files into one:

(function(){
  // código aqui
}()).callThis();

Jsfiddle: http://jsfiddle.net/ZHrPp/

Sometimes we find on the Internet a variation:

(function(){
  // código aqui
}());

Jsfiddle: http://jsfiddle.net/pSK43/


What use is that?

1 answer

13


The main usefulness of these IIFE (function immediately auto-invoked) is to create an enclosure for variables. Thus all variables defined within this enclosure are not exported to the global space, and therefore do not pollute it.

This feature has to do with the normal functioning of the functions and how they create/change the scope of the code. What is different here is that it is immediately invoked/run and does not wait to be called.

The other important reason is that the created variables stay within that scope and are libretted from the memory after the run function, passing their value out if necessary (see example 2 below).

Some practical examples of this application:

Example 1:

(function(global){
  // código aqui
})(this);

In this example we pass into the function the this global space. In the case of client-side javascript this will be window but in the case of Node.JS this will be the global.

Example 2:

// #2479 - IE8 Cannot set HTML of style element
var canChangeStyleHtml = (function(){
    var div = document.createElement('style'),
        flag = false;
    try {
        div.innerHTML = '#justTesing{margin: 0px;}';
        flag = !!div.innerHTML;
    } catch(e){}
    return flag;
})();

This example above I did for the Mootools library to know if the browser in which the code is run can change the HTML of an element <style>. This way the function runs (auto-invoked) returns true or false. So I have this information saved and I can use it in the rest of my code, and I don’t need to run this function anymore.

Example 3:

var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
    (function () {
        var numero = Math.round(Math.random() * 20);
        buttons[i].addEventListener('click', function () {
            alert(numero);
        });
    })();
}

This example shows a cycle for where each iteration runs an IIFE. This function creates a proper scope that is passed and stored. So every time you click a button it will have in memory the value that corresponds to it, without being rewritten. Online example: http://jsfiddle.net/dR8KG/, and by the way the same example without the IIFE: http://jsfiddle.net/dR8KG/1/ - all buttons have the same value.

  • Now I didn’t understand, first you say: "So all the variables inside this enclosure are not exported to the global space, and therefore not polluting it" then at the end you say "So every time you click on a button it will have in memory the value that corresponds to it". Where did we end up? I really didn’t realize.

  • @Jorgeb. in the case of example 3, variables are not available in the global space. They are stored in memory and are called inside the Event Handler. This is very useful to avoid overwriting a variable.

  • 1

    Oh I get it, you have those variables in memory and they’re never going to change, because they’re directly pointed at the button, right?

  • 1

    @Jorgeb. exact! take a look at the console on this fiddle (http://jsfiddle.net/dR8KG/2/) and then take out the comments for the IIFE to be active. In the first case the number value is global and was overwritten until logging only the last value it had. In the second case (after you take the comments //) the variable number is not declared, but exists in memory for each button.

  • 1

    +1 Very cool that, I now realize.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.