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);
}
Since the nested function is a closure it has a reference to the num argument ,the num argument at the end of the loop is 4 .Now when the first element gets clicked why does it alerts 1 ?It should alert 4 .What is the reason for alerting 1 ?Dont it reference to num argument?or what is the reason?
But here the case is different:
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar is now a closure.
bar(10);
The above function will alert 16, because bar can still refer to arg x and tmp, even though it is no longer directly inside the scope.
This proves that the closure also have reference to arguments value than why the above code not alerting 4 everytime?
2 Answers 2
for (var i=0, link; i<5; i++) { //i starts at 0 and iterates up to 4
link = document.createElement("a");
link.innerHTML = "Link " + i;
link.onclick = function (num) {
//num is never changed within this function, and is equal
//to the value of i when it was passed in
return function () { alert(num);};
}(i); //i is passed here
//that sets num to the current value of i for each link
document.body.appendChild(link);
}
For the first link num will be 0, because i was one when it was passed to the outer function. i is then iterated for each turn of the loop and will be a different value for each link.
The pattern here is a very common pattern for preserving the current value of a loop iteration in callbacks/event bindings.
2 Comments
num is preserved by the closure to be the value of i when the onclick property was first set.What you're doing is the classic example to avoid that clicking on the first element will give you 4 instead of 1, which should be the most expected value.
If you want it to alert 1, then just do this:
link.onclick = function() {alert(i);};
But honestly, what would be the point of this? All 4 links would alert 4...
1when clicking on the first element since you are passing the argumentiat the current iteration to the inneronclickfunction which has the argumentnum.