Javascript Closure Problem

て烟熏妆下的殇ゞ 提交于 2019-12-02 18:51:55

问题


I know this kind of question gets asked alot, but I still haven't been able to find a way to make this work correctly.

The code:

function doStuff () {
     for (var i = 0; i< elementsList.length; i++) {
        elementsList[i].previousSibling.lastChild.addEventListener("click", function(){
                   toggle(elementsList[i])}, false);


        }
    } // ends function


    function toggle (element) {
        alert (element);
    }

The problem is in passing variables to the toggle function. It works with the this keyword (but that sends a reference to the clicked item, which in this case is useless), but not with elementsList[i] which alerts as undefined in Firefox.

As I understood it, using anonymous functions to call a function is enough to deal with closure problems, so what have I missed?


回答1:


Try:

function startOfFunction() {
    for (var i = 0; i< elementsList.length; i++) {
        elementsList[i].previousSibling.lastChild.addEventListener(
            "click",
            (function(el){return function(){toggle(el);};})(elementsList[i]),
            false
        );

    }
} // ends function


function toggle (element) {
    alert (element);
}



回答2:


The Problem is, that you want to use the var i! i is available in the onClick Event, (since closure and stuff). Since you have a loop, i is counted up. Now, if you click on any of the elements, i will always be elementsList.length (since all event functions access the same i )!

using the solution of Matt will work.




回答3:


As an explanation: the anonymous function you use in the for loop references the variable "i" to get the element to toggle. As anonymous functions use the "live" value of the variable, when somebody clicks the element, "i" will always be elementsList.length+1.

The code example from Matt solves this by sticking the i into another function in which it is "fixated". This always holds true:

If you iterate over elements attaching events, do not use simple anonymous functions as they screw up, but rather create a new function for each element. The more readable version of Matts answer would be:

function iterate () {
    for (var i = 0; i < list.length; i++) {
        // In here, i changes, so list[i] changes all the time, too. Pass it on!
        list[i].addEventListener(createEventFunction(list[i]);
    }
 }

 function createEventFunction (item) {
     // In here, item is fixed as it is passed as a function parameter.
     return function (event) {
         alert(item);
     };
 }



回答4:


Try:

function doStuff () {
    for (var i = 0; i< elementsList.length; i++) {
        (function(x) {
            elementsList[x].previousSibling.lastChild.addEventListener("click", function(){
               toggle(elementsList[x])}, false);
        })(i);



    }
} // ends function

I think it might be an issue with passing elementsList[i] around, so the above code has a closure which should help.



来源:https://stackoverflow.com/questions/6569005/javascript-closure-problem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!