Last Updated: September 09, 2019
·
1.901K
· gerardsans

JavaScript - Clousures and Immediate functions

Sons of JavaScript Collection | this article

JavaScript always has something cool to it. Besides callbacks and anonymous functions you may find yourself in the need for clousures.

Clousures can adopt the form of an Immediately Invoked Function Expression (IIFE):

(function (parameter1, parameter2) {
  //your code here
}) (a, b) 

Or a simple function:

var closureFn = function(parameter1, parameter2) {
  //your code here
}
... 
var a, b;
closureFn(a, b);
...

An interesting characteristic of clousures is that they carry the scope at the time of their invocation along with them. In the following example safe_i is stored along with the calls so its value is not 5 for all iterations.

As a former C# Developer I found it quite interesting.

Buggy

function buggy() {
  for ( var i = 0; i < 5; i++ ) {
    console.log("Delay: ", i*100);
    setTimeout(function() {
        console.log("i:", i)
    }, i * 100 );
  }
}

Fixed

function fixed() {
  for ( var i = 0; i < 5; i++ ) {
    console.log("Delay: ", i*100);
    (function(safe_i) {
      setTimeout(function() {
        console.log("i:", safe_i)
      }, i * 100 );
    }) (i);
  }
}

You can run the code following the link below. In order to see the console messages you need to toggle the console for your browser Developer Tools.

Demo code: Link

Sons of JavaScript Collection | this article

2 Responses
Add your response

none of this uses closures, and for that matter, "fixed" isn't fixed. if i is 4 when the first function evaluates due to the asynchronous processing nature of js... and you pass that same value of i and assign it to safe_i, then safe_i will now have the same problem you had with i. The key is to create a scope context when the code is executed, not when it's compiled... and you're not doing that. That is commonly done by returning a function which is then executed when the outer function is executed, and that function was compiled with the value of i based on the index of the iteration you are executing.

with your first set of examples, you aren't really doing anything other than creating an anonymous function in the global namespace. nothing is encapsulated (this is still the same context inside and outside the function), it's just difficult to access because it's not named.

over 1 year ago ·

Code should be self explanatory. Only the last code makes use of a closure and fixes the initial problem. Anything else look the demo code. You don't need to agree.

over 1 year ago ·