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
Written by gerardsans
Related protips
2 Responses
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.
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.