Understanding variable capture by closures in Javascript/Node - javascript

Is there a definite source on variable capture in Javascript besides the standard (it's a pain to read the standard)?
In the following code i is copied by value:
for (var i = 0; i < 10; i++)
{
(function (i)
{
process.nextTick(function ()
{
console.log(i)
})
}) (i)
}
So it prints 1..10. process.nextTick is an analog of setTimeout(f,0) in node.
But in the next code i doesn't seem to be copied:
for (var i = 0; i < 10; i++)
{
var j = i
process.nextTick(function ()
{
console.log(j)
})
}
It prints 9 10 times. Why? I'm more interested in a reference/general article than in explaining this concrete case of capture.

I don't have a handy reference. But the bottom line is: In the first, you're explicitly passing in i to an anonymous function, which creates a new scope. You are not creating a new scope for either i or j in the second. Also, JavaScript always captures variables, not values. So you would be able to modify i too.
The JavaScript var keyword has function scope, not block scope. So a for loop does not create a scope.
As a note, the non-standard let keyword has local scope.

In JavaScript, functions enclose variables which were defined in a scope outside of their own in such a way that they have a "living" reference to the variable, not a snapshot of its value at any particular time.
So in your second example, you create ten anonymous functions (in process.nextTick(function(){...})) which enclose the variable j (and i, which always have the same value when the anonymous function is created). Each of these functions use the value of j at a time after the outer for-loop has run entirely, so j=i=10 at the time that each of the functions is called. That is, first your for-loop runs entirely, then your anonymous functions run and use the value of j, which is already set to 10!
In your first example, the situation is a little different. By wrapping the call to process.nextTick(...) in it's own anonymous function and by binding the value of i into a function-local scope by calling the wrapper function (and incidentally shadowing the old variable i into the function parameter i), you capture the value of the variable i at that moment, instead of retaining the enclosed reference to i whose value changes in the enclosure of the inner anonymous functions.
To clarify your first example somewhat, try changing the anonymous wrapper function to use an argument named x ((function (x) { process.nextTick(...); })(i)). Here we clearly see that x takes the value in i at the moment the anonymous function is called so it will get each of the values in the for-loop (1..10).

It is copied (or assigned) in your second example, it's just that there's only one copy of variable j and it will have the value that it last had in it which will be 9 (the last rev of your for loop). You need a new function closure to create a new copy of a variable for each rev of the for loop. Your second example just has one variable that is common to all revs of your for loop, thus it can only have one value.
I don't know of any definitive writeup on this topic.
Variables in javascript are scoped to the function level. There is no block scoping in javascript. As such, if you want a new version of a variable for each rev of the for loop, you have to use a new function (creating a function closure) to capture that new value each time through the for loop. Without the function closure, the one variable will just have one value that will be common to all users of that variable.
When you declare a variable such as your var j = i; at some location other than the beginning of the function, javascript hoists the definition to the top of the function and your code becomes equivalent to this:
var j;
for (var i = 0; i < 10; i++)
{
j = i;
process.nextTick(function ()
{
console.log(j)
})
}
This is called variable hoisting and is a term you could Google if you want to read more about it. But, the point is that there is only function scope so a variable declared anywhere in a function is actually declared once at the top of the function and then assigned to anywhere in the function.

for the first example, i's are not same.
for (var i = 0; i < 10; i++) {
(function (i) { // ๐Ÿ“ธ capture i as the new i in this closure scope.
process.nextTick(function () {
console.log(i) // ๐Ÿž reference new i (captured).
})
})(i)
}
๐Ÿ‘‰ Closures/Value capture - Rosetta Code

Related

why when we defining for loop variable with let, without using IFFE technique we can set specific value of that to a function without loosing it? [duplicate]

This question already has answers here:
JavaScript: Understanding let scope inside for loop [duplicate]
(3 answers)
Closed 1 year ago.
i read MDN pages about const, let, var. the summary of that is before ES2015 we have only global scope and function scope.in [this MDN page][1] there is an example of the benefits of block scope; that shows: instead of using closure concept to save related data for a function, like for loop iteration number, defined the loop variable as let. if the let keyword is only for block scoping how provide us this functionality? are other programming languages have this concept?
let divClassX = document.querySelectorAll('.x');
for (let j = 0; j < 2; j++) {
divClassX[j].onclick = function (event) {
console.log('class x div\'s x ' + j)
}
}
above code has the same functionality as :
let divClassX = document.querySelectorAll('.x');
for (var j = 0; j < 2; j++) {
divClassX[j].onclick = (function (j) {
return function (event) {
console.log('class x div\'s x ' + j)
}
})(j)
}
I assumed that some functionality like that exists so the blow code must work like above but when I clicked on div1 or div2 both times I get 2 but expected one when clicked on div 1 and two when I clicked on div2.
let div1 = document.querySelector('#div1');
let div2 = document.querySelector('#div2');
let i = 1;
div1.onclick = function (event) {
console.log(i);
}
i = i + 1;
div2.onclick = function (event) {
console.log(i);
}
what concept exists that I don't know?
[1]: https://developer.mozilla.org/en-US/docs/Glossary/IIFE
It's more about what scope the variable is defined in than the order in which it's modified.
In your last example, let i occurs in the global scope. Each function you create as an event listener creates its own scope whose parent scope is the global scope. It doesn't matter what i's value was when the function was created, it's the structure of the scope chain that matters. JavaScript looks for variables in increasingly large scopes going up the "chain" of parent scopes. For both functions, i will resolve to the global scope when accessed at the time the function is called, not when the function is created.
As for loops with let, I believe part of the design goal for let was to make loop/event handler (or other nested functions) behaviour more intuitive, and provide an easy way to avoid the common issue where each event handler references the last value of i as opposed to the value when the function was created (i.e. at each iteration of the loop).
In other words, in ES2015 there is a separate scope for each iteration of the loop, and let assigns variables to that scope, not to the surrounding function or the global scope like var. Also when a nested function is called (a function that's inside the for loop), it hits the "iteration" scope first when looking up the scope chain, so it sees the i as it was at the time of iteration.
It's called closure.
A closure is the combination of a function bundled together (enclosed)
with references to its surrounding state (the lexical environment). In
other words, a closure gives you access to an outer functionโ€™s scope
from an inner function. In JavaScript, closures are created every time
a function is created, at function creation time.
In your last snippet
console.log(i);
doesn't print a copy, but the actual variable i (reference), that is initialized with
let i = 1;
and modified with
i = i + 1;

Some questions about closures and an inner IIFE

I was reading this tutualial on javascriptissexy.com. I followed up until the last example.
function celebrityIDCreator (theCelebrities) {
var i;
var uniqueID = 100;
for (i = 0; i < theCelebrities.length; i++) {
theCelebrities[i]["id"] = function (j) { // the j parametric variable is the i passed in on invocation of this IIFE
return function () {
return uniqueID + j; // each iteration of the for loop passes the current value of i into this IIFE and it saves the correct value to the array
} (); // BY adding () at the end of this function, we are executing it immediately and returning just the value of uniqueID + j, instead of returning a function.
} (i); // immediately invoke the function passing the i variable as a parameter
}
return theCelebrities;
}
var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0}];
var createIdForActionCelebs = celebrityIDCreator (actionCelebs);
var stalloneID = createIdForActionCelebs [0];
console.log(stalloneID.id); // 100
var cruiseID = createIdForActionCelebs [1];
console.log(cruiseID.id); // 101
First, I didn't see an IIFE, or at least in the syntax I am familiar with in which there would be a (function()... with the leading left-side parenthesis. Also,
return function () {
return uniqueID + j; // each iteration of the for loop passes the current value of i into this IIFE and it saves the correct value to the array
} ();
Why these two returns? And if this is meant to be an IIFE doesn't need the surrounding parenthesis? Also, how does not j immediately increment to the length of the array as i did in the previous example? Concerning the line theCelebrities[i]["id"] = function (j) { which accesses the element id of the actionCelebs parameter. Why does that property need initially to be set to 0 for each element.
Previous example
// This example is explained in detail below (just after this code box).โ€‹
function celebrityIDCreator (theCelebrities) {
var i;
var uniqueID = 100;
for (i = 0; i < theCelebrities.length; i++) {
theCelebrities[i]["id"] = function () {
return uniqueID + i;
}
}
return theCelebrities;
}
var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0}];
var createIdForActionCelebs = celebrityIDCreator (actionCelebs);
var stalloneID = createIdForActionCelebs [0];
console.log(stalloneID.id()); // 103
Here all of the values are set to 103
Answers to your questions:
IIFE stands for Immediately Invoked Function Expression. In JavaScript, function literals occur in one of two forms: (1) full function definition statements, or (2) expressions. A full function definition statement has function as the leading token of the statement, which means that the statement is not an expression, but just a function definition. It effectively causes a local (or global if in global scope) variable to be created in the current scope with a name equal to the function name as given in the function definition statement, and a value equal to a reference to the function:
function myFunction() {}
myFunction();
When function occurs anywhere (not as the first token) inside an expression, the function definition is said to be "expressionized" and does not automatically create any local variable, but can be stored in a variable by assigning it, or called immediately by following it with a pair of parentheses:
var func = function() { return 7; };
alert(func()); // 7
var funcRes = function() { return 3; }();
alert(funcRes); // 3
Strictly speaking, the term IIFE can refer to any context where a function definition is expressionized and then immediately invoked by following it with a pair of parentheses. You can see in your code example that they do this with the function returning uniqueID + j, and they also do it with the function that encloses said function and simply relays its return value to its parent scope, so both qualify as an IIFE.
In my experience, the term IIFE is used most often to refer to an IIFE that comprises an entire statement, and thus the leading left parenthesis is necessary to exressionize the function definition, for example:
(function() {
var localVar = 3;
alert(localVar);
})();
I think that's why you found the code example slightly unexpected. But both of those 2 function definitions in your code example certainly qualify as IIFEs according to the strict definition of what an IIFE is; as long as the function keyword does not occur as the first token in the statement, then it is expressionized, and can be invoked immediately to form an IIFE.
The two returns are simply necessary as part of the design of the code. Admittedly, the whole thing is quite contrived, and there is a much easier way to accomplish the task, namely, a simple loop that loops through the array and assigns the value of the id hash key to a number incrementing from uniqueID, but they're trying to demonstrate IIFEs, I suppose. The inner return expression computes the next id value from uniqueID and j, which are both closured by the inner function, and returns it from the inner IIFE, and then the outer return relays that return value from the outer IIFE back to the celebrityIDCreator function scope, where it can be assigned.
No, IIFEs do not require surrounding parentheses. To expressionize a function, all that is required is that the function keyword not occur as the first token of the statement.
The full process of closuring is as follows: When a function is defined and contains a variable whose identifier does not bind to any local variable (variable declared with var or function parameter), then it closures around the closest ancestral (thinking of the parse tree) local with that same identifier, or the global if it cannot be bound to any ancestral local. The important point is this: It's a variable reference that is captured by the closure, not a variable value.
In the "Previous example" i closures around the local i that lives in the celebrityIDCreator function scope. Importantly, the function is not immediately invoked, but a reference to the function is stored as the actual value of the id hash key. It is invoked later, during printing. That means that when the function is finally invoked, the variable i has already finished looping through the array, and is now retaining its final value, 103. If the function had been invoked immediately, then i would actually be evaluated during the loop and it would resolve to its current value, which would be the correct incrementing value.
In your main code example, j in the inner IIFE is closuring around the function parameter of the outer IIFE, which is temporary and will never be incremented; that parameter j is a distinct variable from the i in celebrityIDCreator function scope, which is never closured. Also, the inner IIFE is being immediately invoked, so it resolves to the variable's current value anyway. So they've actually overdone it here; there are two reasons why the final assigned value is the proper incrementing value and not the max value (103).
Main point: Closures closure around variables, not values.
The id property did not need to be set to 0 initially; that appears to be just a placeholder. It is overwritten (in both your main example and in the "Previous example") when it is assigned in celebrityIDCreator. And since in the "Previous example" it is overwritten not by another number but by a function, it is a little weird. Again, the whole thing is a little contrived (no offense to the authors...), but all the concepts are there.

Closure (the good way book)

I am going over the 4th chapter of this book and have run into a problem on the code below. This code goes right over my head and I cant seem to figure out why the (i) is there. He explains in the book but its just not that great of an explanation.
//Make a function that assigns event handler functions to an array of nodes the right way
//When you click on a node, an alert box will display the ordinal of the node.
var add_the_handlers = function(nodes){
var i;
for (i = 0; i < nodes.length; i += 1){
nodes[i].onclick = function(i){
return function (e){
alert(i);
};
}(i); // <-------------this i right here.
}
};
Putting (someValue) after a function expression will immediately call that function.
foo = function (i){ ... }(i);
will give you the same result as:
bar = function (i){ ... };
foo = bar(i);
By having a locally scoped variable i inside that function (defined via function (i)), the value is captured (closed over) and won't change when the other i (the one in scope outside the function) changes (which it will every time you go around the loop).
I'd generally use a different name for the variable inside the closure. Duplicate variable names can be confusing.
nodes[i].onclick = function(closed_over_i){
return function (e){
alert(closed_over_i);
};
}(i);
The (i) calls the first anonymous function immediately, meaning that nodes[i].onclick gets the second anonymous function.
There are actually two is there which may be confusing the issue a bit - there is one in the scope of the add_the_handlers function, and another in the onclick function.
I'll rewrite it and number the lines to help explain:
1. var add_the_handlers = function (nodes) {
2. var i;
3. for (i = 0; i < nodes.length; i += 1){
4. nodes[i].onclick = function (j) {
5. return function (e) {
6. alert(j);
7. };
8. }(i);
9. }
10. };
This is functionally identical to your original code; because they're different scopes, your version can have the same variable name without them interfering with each other; it's just a new variable i which is only available within that function. I've changed it to j just to make it clearer where the two scopes are.
On line 4 you define an anonymous function which takes a single argument j, and then call it immediately on line 8 with the current value of i. You do this to create a new scope, copying the current value of i into it. The value of j is no longer linked to the i being incremented by the loop.
This means that you can now define the second anonymous function on line 5 (the closure) in that new scope, so j will always refer to the variable in that scope. You then return that function and assign it to nodes[i].onclick, so when it is called it will always alert the value of i that it was when it was defined, even thought it is now called in a different scope.
Without the function call on line 8, the i on line 6 of your example would be in the scope of the outer function starting at line 1; because that value is changed in the loop on line 3 for each item in the array, all onclick functions would alert the final value of i, nodes.length.
The example code is just a more compact and confusing way of writing:
var create_closure = function (val) {
// This val is in a separate scope to the i
return function (e) {
// This is the closure; it references a variable in the parent scope
alert(val);
};
};
var add_the_handlers = function (nodes){
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = create_closure(i);
}
};
Although the example is making a point, in general this will be a better way to write the solution - less nesting and a named function makes it clearer to anyone coming along afterwards, and less likely you'll make a mistake with it later. At the very least use a different variable name in your closure.

Understanding closure in Javascript

I'm trying to wrap my head around closures in Javascript.
Here is an example from a tutorial:
function greeter(name, age) {
var message = name + ", who is " + age + " years old, says hi!";
return function greet() {
console.log(message);
};
}
// Generate the closure
var bobGreeter = greeter("Bob", 47);
// Use the closure
bobGreeter();
The author said that this is an effective way of using closure to make private variables, but I don't get the point.
Could someone enlighten the benefits of coding like this?
A closure is a pair of a function and the environment in which it was defined (assuming lexical scoping, which JavaScript uses). Thus, a closure's function can access variables in its environment; if no other function has access to that environment, then all of the variables in it are effectively private and only accessible through the closure's function.
The example you provided demonstrates this reasonably well. I've added inline comments to explain the environments.
// Outside, we begin in the global environment.
function greeter(name, age) {
// When greeter is *invoked* and we're running the code here, a new
// environment is created. Within this environment, the function's arguments
// are bound to the variables `name' and `age'.
// Within this environment, another new variable called `message' is created.
var message = name + ", who is " + age + " years old, says hi!";
// Within the same environment (the one we're currently executing in), a
// function is defined, which creates a new closure that references this
// environment. Thus, this function can access the variables `message', `name',
// and `age' within this environment, as well as all variables within any
// parent environments (which is just the global environment in this example).
return function greet() { console.log(message); };
}
When var bobGreeter = greeter("Bob", 47); is run, a new closure is created; that is, you've now got a new function instance along with the environment in which it was created. Therefore, your new function has a reference to the `message' variable within said environment, although no one else does.
Extra reading: SICP Ch 3.2. Although it focuses on Scheme, the ideas are the same. If you understand this chapter well, you'll have a good foundation of how environments and lexical scoping work.
Mozilla also has a page dedicated to explaining closures.
The purpose of a closure is so that the variables you use inside a given function are guaranteed to be "closed" which means they do not depend on external variables - they only depend on and use their arguments. This makes your Javascript methods closer to a pure function, that is, one that returns the same value for the same given arguments.
Without using closures, your functions will be like Swiss cheese, they will have holes in them. A closure plugs up those holes so the method doesn't depend on variables higher in the scope chain.
Now, up until this point, my answer has been simply about organizing your code and style. So take this simple example. At the line with the comment, I invoke a function and the value of the variable a is captured for future use.
var a = "before";
var f = function(value) {
return function()
{
alert(value);
}
} (a); //here I am creating a closure, which makes my inner function no longer depend on this global variable
a = "after";
f(); //prints "before"
Now, why would you need to do this? Well, here's a practical example. Consider the following code that uses jQuery to add 5 links to the document. When you click a link, you would expect it to alert the number associated with the link, so clicking the first you would think would alert 0, and so on. But, this is not the case, each link will alert the value of 5. This is because the function I define depends on the variable i which is being modified outside the context of the function. The function I pass into bind is a Swiss cheese function.
for (var i = 0; i < 5; i++)
{
var a = $('<a>test link</a>').bind('click', function(){
alert(i);
});
$(a).appendTo('body');
}
Now, let's fix this by creating a closure so each link will alert its correct number.
for (var i = 0; i < 5; i++)
{
var fn = function (value) {
return function() {
alert(value);
};
} (i); //boom, closure
var a = $('<a>test link</a>').bind('click', fn);
$(a).appendTo('body');
}
I don't think this is a good example for private variables, because there are no real variables. The closure part is that the function greet can see message (which is not visible to the outside, hence private), but it (or anyone else) is not changing it, so it is more of a constant.
How about the following example instead?
function make_counter(){
var i =0;
return function(){
return ++i;
}
}
var a = make_counter();
console.log(a()); // 1
console.log(a()); // 2
var b = make_counter();
console.log(b()); // 1
console.log(a()); // 3
A better example may be
function add(start, increment) {
return function() {
return start += increment;
}
}
var add1 = add(10, 1);
alert(add1()); // 11
alert(add1()); // 12
Here, every time you call the returned function, you add 1. The internals are encapsulated.
The returned function still has access to its parents variables (in this case, start and increment).
On a lower level of thinking, I think it means that the function's stack is not destroyed when it returns.
Once you "get it" you will wonder why it took you so long to understand it. That's the way way I felt anyways.
I think function scope in Javascript can be expressed fairly concisely.
The function body will have access to any variables that were visible in the lexical environment of the function declaration, and also any variables created via the function's invocation -- that is, any variables declared locally, passed through as arguments or otherwise provided by the language (such as this or arguments).
It's called "closures" because they are "closed" around free variables, and there are much more ways to use it then only hiding state. For example, in functional programming, where closures came from, they are often used to reduce parameters number or set some constant for a function. Let's say you need function goodEnough() that will test if some result is better then some threshold. You can use function of 2 variables - result and threshold. But you can also "enclose" your constant inside function:
function makeThresholdFunction(threshold) {
return function(param) {
return (param > threshold);
}
}
var goodEnough = makeThresholdFunction(0.5);
...
if (goodEnough(calculatedPrecision)) {
...
}
With closures you can also use all the tricks with functions such as their composition:
function compose(f1, f2) {
return function(arg) {
return f1(f2(arg));
}
}
var squareIncremented = compose(square, inc);
squareIncremented(5); // 36
More on closure design and usage can be found at SICP.
I found this a pretty helpful article.
When is a function not a function?
//Lets start with a basic Javascript snippet
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(i);
}
return denomination;
}
This a basic function statement in Javascript that returns an array of [10,20,30]
//--Lets go a step further
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(console.log(i));
}
return denomination;
}
This will print 10, 20 ,30 sequentialy as the loop iterates, but will return an array of [undefined, undefined, undefined], the major reason being we are not pushing the actual value of i, we are just printing it out, hence on every iteration the javascript engine will set it to undefined.
//--Lets dive into closures
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(function() {
console.log(i)
});
}
return denomination;
}
var dn = generateCash();
console.log(dn[0]());
console.log(dn[1]());
console.log(dn[2]());
This is a little tricky, what do you expect the output will be, will it be [10,20,30]? The answers is no, Lets see how this happens. First a Global execution context is created when we create dn, also we have the generatecash() function. Now we see that as the for loop iterates, it creates three anonymous function objects, it might be tempting to think that the console.log within the push function is getting fired too, but in reality it is not. We haved invoked generateCash(), so the push function is just creating three anonymous function objects, it does not trigger the function. At the end of the iteration, the current local context is popped from the execution stack and it leaves the state of i : 40 and arr:[functionobj0(), functionob1(), functionobj2()].
So when we start executing the last three statements, all of them output 40, since it is not able to get the value of i from the current scope, it goes up the scope chain and finds that the value of i has been set to 40. The reason all of them will fire 40 is beacause every single component of dn lies in the same execution context and all of them on being not able to find the value of i in their current scope will go up the scope chain and find i set as 40 and output it respectively

Please explain the use of JavaScript closures in loops [duplicate]

This question already has answers here:
JavaScript closure inside loops โ€“ simple practical example
(44 answers)
Closed 6 years ago.
I have read a number of explanations about closures and closures inside loops. I have a hard time understanding the concept. I have this code: Is there a way to reduce the code as much as possible so the concept of closure can be made clearer. I am having a hard time understanding the part in which the i is inside two parenthesis. Thanks
function addLinks () {
for (var i=0, link; i<5; i++) {
link = document.createElement("a");
link.innerHTML = "Link " + i;
link.onclick = function (num) {
return function () {
alert(num);
};
}(i);
document.body.appendChild(link);
}
}
window.onload = addLinks;
WARNING: Long(ish) Answer
This is copied directly from an article I wrote in an internal company wiki:
Question: How to properly use closures in loops?
Quick answer: Use a function factory.
for (var i=0; i<10; i++) {
document.getElementById(i).onclick = (function(x){
return function(){
alert(x);
}
})(i);
}
or the more easily readable version:
function generateMyHandler (x) {
return function(){
alert(x);
}
}
for (var i=0; i<10; i++) {
document.getElementById(i).onclick = generateMyHandler(i);
}
This often confuse people who are new to javascript or functional programming. It is a result of misunderstanding what closures are.
A closure does not merely pass the value of a variable or even a reference to the variable. A closure captures the variable itself! The following bit of code illustrates this:
var message = 'Hello!';
document.getElementById('foo').onclick = function(){alert(message)};
message = 'Goodbye!';
Clicking the element 'foo' will generate an alert box with the message: "Goodbye!". Because of this, using a simple closure in a loop will end up with all closures sharing the same variable and that variable will contain the last value assigned to it in the loop. For example:
for (var i=0; i<10; i++) {
document.getElementById('something'+i).onclick = function(){alert(i)};
}
All elements when clicked will generate an alert box with the number 10. In fact, if we now do i="hello"; all elements will now generate a "hello" alert! The variable i is shared across ten functions PLUS the current function/scope/context. Think of it as a sort of private global variable that only the functions involved can see.
What we want is an instance of that variable or at least a simple reference to the variable instead of the variable itself. Fortunately javascript already has a mechanism for passing a reference (for objects) or value (for strings and numbers): function arguments!
When a function is called in javascript the arguments to that function is passed by reference if it is an object or by value if it is a string or number. This is enough to break variable sharing in closures.
So:
for (var i=0; i<10; i++) {
document.getElementById(i).onclick =
(function(x){ /* we use this function expression simply as a factory
to return the function we really want to use: */
/* we want to return a function reference
so we write a function expression*/
return function(){
alert(x); /* x here refers to the argument of the factory function
captured by the 'inner' closure */
}
/* The brace operators (..) evaluates an expression, in this case this
function expression which yields a function reference. */
})(i) /* The function reference generated is then immediately called()
where the variable i is passed */
}
I've been programming in JavaScript for a long time, and "closure in a loop" is a very broad topic. I assume you are talking about the practice of using (function(param) { return function(){ ... }; })(param); inside of a for loop in order to preserve the "current value" of the loop when that inner function later executes...
The code:
for(var i=0; i<4; i++) {
setTimeout(
// argument #1 to setTimeout is a function.
// this "outer function" is immediately executed, with `i` as its parameter
(function(x) {
// the "outer function" returns an "inner function" which now has x=i at the
// time the "outer function" was called
return function() {
console.log("i=="+i+", x=="+x);
};
})(i) // execute the "closure" immediately, x=i, returns a "callback" function
// finishing up arguments to setTimeout
, i*100);
}
Output:
i==4, x==0
i==4, x==1
i==4, x==2
i==4, x==3
As you can see by the output, all of the inner callback functions all point to the same i, however, since each had its own 'closure', the value of x is actually stored as whatever i was at the time of the outer function's execution.
Commonly when you see this pattern, you would use the same variable name as the parameter and the argument to the outer function: (function(i){ })(i) for instance. Any code inside that function (even if executed later, like a callback function) is going to refer to i at the time you called the "outer function".
Well, the "problem" with closures in such a case is, that any access to i would reference the same variable. That is because of ECMA-/Javascripts function scope or lexical scope.
So to avoid that every call to alert(i); would display a 5 (because after the loop finished i === 5), you need to create a new function which invokes itself at runtime.
To achieve this, you need to create a new function, plus you need the extra paranthesis at the end, to invoke the outer function immediately, so link.onclick has now the returned function as reference.
A closure is a construct in which you reference a variable outside the scope in which it's defined. You usually talk about closures in the context of a function.
var helloFunction;
var finished = false;
while (!finished) {
var message = 'Hello, World!';
helloFunction = function() {
alert(message);
}
finished = true;
}
helloFunction();
Here, I define the variable message, and define a function that references message. When I define the function to use message, I am creating a closure. This means helloFunction holds a reference to message, so that I can continue to use message, even outside of the scope (the loop body) where message is defined.
Addendum
The (i) in parenthesis is a function call. What's happening is:
You define some function(num) {}. This is called an anonymous function, because it's defined inline and doesn't have a name.
function(num) takes an integer argument, and returns a reference to another function, which is defined as alert(num)
The outer anonymous function is immediately called, with the argument i. So num=i. The result of this call is a function which will do alert(i).
The end result is more or less equivalent to: link.onclick = function() { alert(i); };
To answer the last part of your questions. The two parenthesis invoke the function as any other functions. Why you do it here is that you want to keep what the variable "i" is just at that time. So what it does is, invoke the function, the i is sent as a argument "num". Since it's invoke it will remember the value nume in variable links own scoop.
If you did't to this all link click would result in an alert saying "5"
John Resig, founder of jQuery, has a really nice online presentation explaining this. http://ejohn.org/apps/learn/
..fredrik

Categories