Javascript Infamous Loop Issue Revisited
The infamous loop issue in Javascript continues to baffle developers. Consider the following code snippet:
function addLinks () { for (var i=0, link; i<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function () { alert(i); }; document.body.appendChild(link); } }
This code is intended to create 5 links, each with an onClick event that displays the current link ID. However, when these links are clicked, they all display "link 5".
The root cause of this issue lies in Javascript's function-level scoping. When the loop completes, the i variable retains the value of 5. This is because Javascript functions are closed over their lexical environment, meaning they have access to the variables defined in the surrounding scope.
A workaround for this issue is to introduce a closure that captures the current value of i for each iteration:
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); } }
In this code, a new function object is created for each link. It has its own scope and a local variable num, which is assigned the current value of i. When the inner function is executed, it refers to the num variable of the closure, which retains the correct value assigned in the loop.
While this approach is effective, it incurs a performance penalty as a new function is created for every event listener. A more efficient alternative is to use the DOM node itself for data storage:
function linkListener() { alert(this.i); } function addLinks () { for(var i = 0; i < 5; ++i) { var link = document.createElement('a'); link.appendChild(document.createTextNode('Link ' + i)); link.i = i; link.onclick = linkListener; document.body.appendChild(link); } }
By storing the i value directly on the DOM node, we eliminate the need for closures, thus improving the code's efficiency.
The above is the detailed content of Why Do Javascript Loops Cause Unexpected Behavior in Event Handlers?. For more information, please follow other related articles on the PHP Chinese website!