Take below code iterates over 6 input buttons and attaches an onclick event to every button that alerts the index number of the respective iteration:
for (var i = 1; i < 6; ++i) {
var but = document.getElementById('b_' + i);
(function (el) {
var num = i;
but.onclick = function () {
alert(num);
};
})(but);
}
As you can see, in each iteration there is a self-invoking function that creates a scope to store the iteration index in that scope.
I have always used this type of pattern to attach an event that is dependant on a variable that is changed during iterations.
Can anyone explain to me exactly why the above works, and how the num variable is captured in the scope?
Also, is the self-invoking function used above called a closure ?
Yes this is a closure.
Everytime a function is executed a new object is created to hold (as its properties) the variables that are declared with var and every function declared inside it. This object is called the execution context (or sometimes the scope object).
Everytime a function is declared (or defined in an expression) the new function has attached to it the execution context object that is current. This creates what is known as a scope chain.
When executing code needs to resolve an identifier to a value it first looks for it in the properties of the current execution context. If the identifier is not found it uses the exection context object attached to the function that is being executed. It keeps going up the scope chain until it reaches the global level.
In your example each time "self-invoking function" gets executed a new execution context object is create holding the properies el and num. Since the function assigned to onclick is created inside this execution context you will get a new instance of this function each time. These instances will each have the corresponding execution context object attached. Hence the first will have the execution context when num has been assigned 1, the second will have the execution context where num has been assigned 2 and so on.
When each of the onclick functions run the code will initially look for the identifier num in the current execution context. However this inner function doesn't var a num so its not found. So Javascript looks to the execution context attached to the function when it was created. Here it will find num, the num will contain the value assigned to it during that iteration as described above.
Hey guys. Yep it is a closure. If you want to know what exactly occurs when function is creating then study following article.
http://www.jibbering.com/faq/faq_notes/closures.html
Wouldn't that mean that the var i defined outside the closure is a global variable, thus giving the self-invoking function access to it?
Each time through the loop, evaluating function (el) {...} creates a new anonymous function, which is immediately invoked. Within the anonymous function, a variable named num is created (because JS doesn't do static variables, it's a new one each time). num is assigned the value of i when the function is invoked (which is immediately). This gives us 6 anonymous functions and 6 nums, each holding the values 1 through 6.
With each invocation of the anonymous function, an inner anonymous function is created and stored as the click handler. The inner function references a num. As a result, a closure is created which ensure that when the outer function exits, num isn't destroyed. Should the inner function ever be discarded, num will soon follow.
for (var i = 1; i < 6; ++i) {
var but = document.getElementById('b_' + i);
(function (el) {
var num = i;
but.onclick = function () {
alert(num);
};
})(but);
}
Now lets start the execution of the loop
initially i=1,but= domelement with id ='b1'
now comes the function invoke,
ok it calls the inner function(with parameter el) with value of parameter of but('b1')
and starts executing it that is what invoking actually means execute it now.
Now inside it ,
new instance of num is assigned 1
but.onclick is assigned a function so stores function in memory also sees that it accesses num so num is now closed variable that means its lifetime is increased so as to be accessed by onclick function when invoked.
Next iterationnow value of i=2,but= domelement with id ='b2'
now comes the function invoke,
it calls the inner function(with parameter el) with value of parameter of but(value='b2') .
Now inside it ,
new instance of num is assigned 2
but.onclick is assigned a function so stores function in memory also sees that it accesses num so num is now closed variable that means its lifetime is increased so as to be accessed by onclick function when invoked.
Similary all others are exectuted till the loop terminates.
Related
I am pretty new in JavaScript and I am studying the following topics: closure and IIFE (Immediately-invoked function expression).
So I have the following example related to the closure concept, it is very commented:
/* Classical example as far as why closure can make your code look hard to anticipate, but understanding how works is "simple"
*/
function buildFunctions() {
var arr = []; // Create an empty array
for (var i = 0; i < 3; i++) {
/* Add a new function to this array, identical functions but are 3 differents functions:
*/
arr.push(
function() { // It is not invoking the function, it is just creating it
console.log(i); // i= 0, 1, 2
}
)
}
return arr;
}
var fs = buildFunctions(); // Call the build() function that put the 3 functions inside the array
/* When these functions are actually invoked and it looks at the 'i' variable they use the OUTER REFERENCE inside their execution context. So what will be the values? You might expect that the values will be 0, 1, 2 but this is wrong because at the end of the for loop inside the buildFunctions() function the value of the 'i' variable is 3. So when the anonymous functions inside the arrays are invoked they use the OUTER REFERENCE and the CLOSURE CONCEPT to access to the memory space related to the popped of fbuildFunctions() function that contain the variables of this function, and here the 'i' value is 3 !!!
N.B: Many people think that the result should be 0,1,2 because they think that when the function is pushed into the array it is invoked but it is not !!! The function is invoked here:
*/
fs[0](); // Invoke the first function inside the array, the value is 3
fs[1](); // Invoke the second function inside the array, the value is 3
fs[2](); // Invoke the third function inside the array, the value is 3
/* What have I to do if I want this works? (I want that the first function return 0, the second return 1 and the third return 3).
In order to preserve the value of 'i' for the inner anonymous function I am going to need a separate execution context for each of the functions that I am pushing into the array. I need a parent scope that holds the current values of 'i' variable as the loop goes on. So, the only way to get an execution context is to execute a function. To execute a function on the fly I use IIFE concept.
In this way every time that the loop runs, differently from the previous example, the anonymous inner function is executed passing to it the current value of the 'i' variable. This value is so stored in the 'j' variable in the execution context of the current performed anonymous inner function.
So at first time pass 0, at the second time pass 1, at the third time pass 3 and these 3 values are stored in the 'j' variable of the related execution context.
*/
function buildFunctions2() {
var arr = []; // Create an empty array
for (var i = 0; i < 3; i++) {
arr.push(
(function(j) {
return function() {
console.log(j); // print the current value
}
}(i)) // I use IIFE concept to invoke the function passing the current value of the 'i' variable
)
}
return arr;
}
var fs2 = buildFunctions2(); // Call th build() function that put the 3 functions inside the array
/*
When these functions are performed don't use closure concept because it have not to use the outer reference but use the 'j' value inside the current function execution context.
*/
fs2[0]();
fs2[1]();
fs2[2]();
I have perfectly clear how the closure works but I have some doubts about the second example of the previous example, the one related to the buildFunctions2() function.
So the first example show the closure concept and the fact that, following the outer reference of each performed functions the program reach the memory space related to the variable of the buildFunctions() also if its execution context was popped off the execution context stack. So the result will be always the same for all the 3 functions, and it will be 3.
This is perfectly clear for me.
The second example intend to obtain the values 0, 1 and 3 when I perform the 3 functions putted inside the array.
To obtain this behavior the buildFunctions2() perform a for loop that put a function inside the current element of the array using the IIFE concept, in fact:
for (var i = 0; i < 3; i++) {
arr.push(
(function(j) {
return function() {
console.log(j); // print the current value
}
}(i)) // I use IIFE concept to invoke the function passing the current value of the 'i' variable
)
}
That, from what I have understand, it means that each time that enter in the for loop a new anonymous function is added to the array and performed passing to it the 'i' value as parameter. So in this way I am not using the closure concept because no my functions print the 'j' values that are in the context of these anonymous functions. Is it my reasoning correct?
The thing that I can't understand is: if the function is added to the array and performed, why have I also to add:
fs2[0]();
fs2[1]();
fs2[2]();
to obtain the result in the FireBug console? If I remove these 3 lines that invoke the function associated to all the elements of my array I obtain no result.
This seems strange to me because, from what I have understand, using the IIFE, I add a function to the array and I automatically perform it passing to it the current 'i' value (that is 0,1,2) so why after have I to explicitly perform the functions?
What am I missing?
If you look at this part of the code:
(function(j) {
return function() {
console.log(j);
}
}(i))
You'll notice that there are two functions. The outer one is an IIFE, and will be executed immediately when this part of the code is run.
What this outer function does is define another function (the inner one), which uses the value of j that is local to the outer function (passed as a parameter). This function, however, is not executed (like in the first example), and just returned, to be executed later when you run fs2[0]().
Examples of the different between definition and execution:
function fn1(a) { } // defines a function named fn1, does not execute it
fn1(123); // executes the function defined above
fn2 = function(a) { } // defines an anonymous function, does not execute it, then stores it in fn2
fn2(234); // executes the function defined above
(function(a) { } )(345); // defines an anonymous function, and executes it right away: that's an IIFE
How the variable 'str2' is available inside the callback method passed to display method?
str2 should be visible only inside function 'name'.
a = {
display: function (n){
console.log("I am inside display method");
n();
}
}
function name(a,str2)
{
a.display(function (){
console.log(str2);
})
}
name(a, 'ddd');
Variable scoping in Javascript is hierarchical. Lower scopes have access to all variables of all higher scopes. Here's an example:
function outer() {
var foo = 2;
function inner() {
console.log(foo); // 2
}
}
It doesn't matter if a variable is passed as a parameter or if it was defined as a local var.
Yes str should be visible only inside function 'name' yes it is working same you said, in JavaScript function declarations loads before any code is executed, and scope depend on execution context
in your code scope of str2 is inside name() function and you call a.display() within this scope (within scope of name()) that's why str2 available inside display() at the time of execution.
To evaluate name(a, 'ddd'), the compiler will create a new stack frame and place two slots on it, one a, which will be a reference to the global object of the same name, and str2, which will contain the string literal 'ddd'. Then the body will be evaluated.
In the body, to evaluate a.display(function(){...}), the value of a.display will be resolved to the function with parameter n. To evaluate n(function(){...}), a new stack frame will be created with n assigned to the closure that results from evaluating the anonymous callback (a closure being a combination of a pointer to the static scope of the function and the compiler generated code for the function itself). Then the body of the a.display function will be evaluated.
In the body, the console.log will be called with the given string. Then the callback n() will be evaluated. Since n doesn't take any parameters, it will just be evaluated in the topmost stack frame, so when the time comes to evaluate console.log(str2), str will not be found on the current stack frame, so the compiler will follow the scope chain all the way to the frame where we bound 'ddd' to str and a to the function.
That's a pretty long answer to your simple question. I'll try to shorten it later. Also, corrections are welcome, as I'm being very hand-wavy with the evaluation process.
In Javascript the variable declared on a certain scope is available in every inner scope. In this case it's a concept called "closure". This answer might give you good insight about scoping in Javascript: What is the scope of variables in JavaScript?
Hope this simple example can help you understand its usefulness:
function counter () {
var votes = 0;
this.upvote = function() { votes++; }
this.downvote = function() { votes--; }
this.getValue = function() { return votes; }
}
var counter1 = new counter();
counter1.upvote();
console.log(counter1.getValue()) // Prints 1
counter1.upvote();
counter1.upvote();
console.log(counter1.getValue()) // Prints 3
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.
Crockford had this example to keep myArray from being in the global scope:
var myName = (function() {
var myArray = ['zero','one','two','three','four'];
return function(X) {
return myArray[X];
}
}()); // This function is invoked immediately
result = myName(3); // Now invoke it "for real"
Q: I don't get why it isn't
var myName = (function(X) {
Q: When I call myName(3), isn't "var myArray=" executed a 2nd time?
Suppose it's not executed a 2nd time because JavaScript knows that it's already been defined... What about a loop or some other logic between the var stmt and the return function stmt? Wouldn't it be executed every time?
Q: Can you name the subfunction and call it instead of calling myName?
okay, let's break this down...
var myName = (function(){
...
}());
that piece sets myName to whatever that anonymous function returns, so if it were:
var myName = (function(){ return 42; }());
myName would equal 42. If that doesn't make sense, this is the same thing:
function someFunction(){ return 42; }
var myName = someFunction();
So in your example, myName is set to function(X){ return myArray[X] }. So myName is a function. When you call it, the only code that is run is return myArray[x]. myArray is kept in what is called a closure, it is only exposed to the myName function and the anonymous one surrounding it.
I wrote an article on closures years back that may help you: http://www.htmlgoodies.com/primers/jsp/article.php/3606701/Javascript-Basics-Part-9.htm (scroll down to the "Closures" header).
OK here it goes ..
answer to Q1 . it is not myName = (function(x) because the part inside the brackets returns a function which takes X . i.e. myname is not assigned to (function(){}) but to the return value of it .
Q2. No when u calll myName 2nd time it already points to the inner function hence the outer function is not invoked at all .(this is the sepciality of closures where the value stays alive in inner function even if outer functions are completed.)
Q3. Well nopes we can name the inner function but the name will be valid only inside the outer function and since outer function has completed the name would be useless.
The outer function doesn't have to have an argument X, because it's only purpose is to return another function (which then is parametrized). Thus no argument is needed here.
Thus the only effect is to bind the function(X)... thing to the variable myName. Therefore no other constructs like loops or so does make sense here.
Q1+2: Note the () right of the comment "This function is invoked immediately". The outer function defined is not stored in myName, but immediatly called. Itself then returns an anonymous function which has no name and requires a single parameter (X). This function beeing returned is stored in myName.
To grasp closure you should start thinking about functions just as another value of a variable which can be stored and returned jsut as any other value.
Q3: myName is the subfunction.
Okay answer in turn:
First, why it's var myName = (function() { and not var myName = (function(x) {
In this case because the x value isn't required to create the function you are returning. The data structure of the array contained in the returned function is hard coded and so you don't need additional information to construct it. Much in the same way that
function a() {
return 1 + 2;
}
Doesn't have any arguments, because it's values are hardcoded. This is an example of functions as data or first class functions
Question two: is var myArray executed every time.
The short of it is no. myArray has been assigned to at this point so it has a value that the system has already calculated. In this case it's a function. The myArray potion has been set and so there is no cause to keep executing it. If the outer function didn't return a new function then yes it would need to get called again and again but that would defeat the purpose of this abstraction.
Question three: can you call the inner function.
No, it's out of scope. The entire point of this example is that you have defined a function generator.
Answer to first question:
no, the first "line" is returning a function so when you call "myName" you are actually executing the returned function
function(X) {
return myArray[X];
}
Answer to second question
no, such a function can still refer to the array "myArray"... in fact the purpose of this closure is to make myArray available in the global scope
In words:
myName is the result of an immediately executed anonymous function. It returns a function reference (to an anonymous function). That function has one parameter: X. After execution of the topmost anonymous function, myName is a reference to the inner anonymous function.
Now the inner anonymous function has access to myArray via a closure (myArray and the returned anonymous function both live within the scope of the topmost anonymous function). So if you execute myName, you actually execute the inner anonymous function, which can access myArray.
The topmost anonymous function is executed immediately and once (it returns a reference to the inner function). So myArray is declared within that execution context, and only once.
Since the definition of the myName object (function) ends in '()', its function is called immediately, returning a new function which has the myArray variable statically bound to it. myName is then accessible globally but myArray is not as it is within a function closure. When you reference myName() it has exclusive access to the bound array.
This approach ensures that myArray is only allocated once, when the outer function 'is invoked immediately'. After it is invoked, myArray isn't in the global scope, but is still available to the anonymous inner function.
The approach you proposed would work, but would require that the array be allocated each time the function was called. (Or be allocated outside the function, in the global scope.)
In Javascript, I am sometimes too immerged in the idea that a function creates a new scope, that sometimes I even think the following anonymous function will create a new scope when it is being defined and assigned to onclick:
ha link 1
ha link 2
ha link 3
ha link 4
ha link 5
<script type="text/javascript">
for (i = 1; i <= 5; i++) {
document.getElementById('link' + i).onclick = function() { var x = i; alert(x); return false; }
}
</script>
but in fact, the anonymous function will create a new scope, that's right, but ONLY when it is being invoked, is that so? So the x inside the anonymous function is not created, no new scope is created. When the function was later invoked, there is a new scope alright, but the i is in the outside scope, and the x gets its value, and it is all 6 anyways.
The following code will actually invoke a function and create a new scope and that's why the x is a new local variable x in the brand new scope each time, and the invocation of the function when the link is clicked on will use the different x in the different scopes.
ha link 1
ha link 2
ha link 3
ha link 4
ha link 5
<script type="text/javascript">
for (i = 1; i <= 5; i++) {
(function() {
var x = i;
document.getElementById('link' + i).onclick = function() { alert(x); return false; }
})(); // invoking it now!
}
</script>
If we take away the var in front of x, then it is a global x and so no local variable x is created in the new scope, and therefore, clicking on the links get all the same number, which is the value of the global x.
Update: the question is: we have to be careful when we analyze code, that a function will not create a scope when it is merely defined and assigned. It has to invoked. Is that so?
You're right, but you're also confusing yourself. Rather than thinking of functions as just "making a new scope" understand what's really happening instead. Javascript interprets a variable by looking at a scope chain. If the variable is not present in the function's scope, it will go up to the enclosing level's scope in the case of a closure. That part happens at the time the variable is interpreted. The scope itself is created when the function is, but where you're getting confused is nothing is "captured" in the scope at that time. It's just augmenting a scope chain.
That's why putting closures in loops is such a "gotcha" in javascript programming--you are right to put in in an auto-executing anonymous function if you want to capture the value of i at the time of function declaration. People tend to think (especially coming from procedural languages) that the outer scope is frozen and all current values are passed into the new function scope, and that's not true.
The Scope of a function is set when the function object is created, for example:
var fn;
// augment scope chain:
with ({foo: "bar"}) {
fn = function () { // create function
return foo;
};
}
// restored scope chain
fn(); // "bar"
In the above example, the function is created inside the with block, there the current scope is being augmented, to introduce the object with the foo property to the scope chain.
In your second example, happens the same, the onclick handler function is being created inside the auto-invoking anonymous function, which itself has created a new lexical scope.
At the moment that function is auto-invoked on each loop iteration, the value of i is captured into that scope in the x variable, then the onclick handler function is created inside that scope, and it will be able to resolve it.
I do not understand your question, but I do not see anything weird or wrong with that.
In the first case, a closure is formed, and when the event is invoked, it creates its own scope and fetches the value from i in its outer scope, maintained due to the closure. But that code has already been executed so i = 6 because the loop is long finished, and thus, x = 6.
In the latter example, its the same thing, you are creating a closure, and when the event gets invoked it will fetch x from its outer scope, maintained by the closure, but it already executed, and since it ran immediately in the loop, this time x is equal to the i at the time the function was ran (to create the closure).