0

ループidで生成される変数があります。for何らかの理由で、idが渡されると0から1に変わりますcallback。私の推測では、idパラメーターを誤って渡しています。

    refreshMenu: function(mods, callback){
    var menu = document.getElementById('menu'), 
            ul = document.createElement('ul');

    menu.innerHTML = ''; 
    menu.appendChild(ul);

    for(var id = 0; id < mods.length; id++){
        var li = document.createElement('li'), 
        that = this;


            ul.appendChild(li);

            li.setAttribute('id', id);
            li.innerHTML = mods[id].get('name');

            console.log(id); // HERE ---> 0

            li.addEventListener('click', function(){
                that.selectMenu(li, function(){

                    console.log(id); HERE ---> //1 ?

                that.selectList(id - 1);

                });
            }, false);
        }

        callback();
    }, 

    selectList: function(id)
        var activeList = this.activeList();

        console.log(id);

        if (activeList.id == id){
            return;
        } 
        else if (activeList){
            activeList.setAttribute('class', '');
        };

        var target = document.getElementById(id);
        target.setAttribute('class', 'activeList');
    },  

    selectMenu: function(li, callback){
        if(li.className == 'activeMenu') 
            return; 

        var active = document.getElementsByClassName('activeMenu')[0];
        if(active)      
            active.setAttribute('class', '');

        li.setAttribute('class', 'activeMenu');

        callback();
    },
4

2 に答える 2

3

forループ内にクロージャを構築する場合、これは非常に一般的な落とし穴です。作成しているすべての関数は同じid変数を参照し、forループは変数を変更します。

これを修正する簡単な方法の1つは、これらの関数を作成するヘルパー関数を作成し、ヘルパーに独自のパラメーターを取得させることです。

// In the body of the for loop ...
var makeClickFunction = function (li, id) {
    return function (){
        that.selectMenu(li, function(){
                               console.log(id);
                               that.selectList(id - 1);
                            });
    };
};
li.addEventListener('click', makeClickFunction(li, id));

ヘルパーのid引数のバインディングは、 forループのバインディングをシャドウイングします。これは、良いことです。私たちは意図的にこれを行っています。liも保持する必要があるため、liもキャプチャします。

後で、makeClickFunctionを呼び出して、 forループ 内で現在の値を渡します。forは引き続きIDを変更しますが、それは問題ありません。その変更は、 makeClickFunctionのクロージャの動作とは関係ありません。

于 2012-09-24T02:53:14.183 に答える
1

の値はid、コールバックが呼び出される前にすでに変更されているため、コールバックが呼び出されるときに正しいID値が必要な場合は、クロージャーが必要です。

        li.addEventListener('click', function(){
            that.selectMenu(li, function(){

                console.log(id); HERE ---> //1 ?

            that.selectList(id - 1);

            });
        }, false);

==>

li.addEventListener('click', 
(function(li,that,id){
    return function(){
        that.selectMenu(li, function(){
        console.log(id); 
        that.selectList(id - 1);
        })
    }
})(li,that,id),
false);
于 2012-09-24T02:28:30.807 に答える