2

我了解以下代码块中发生了什么,但不确定如何修复它:

for (var i = 0; i < songs.length; i++){
    var listItem = $('<li/>').appendTo(songList);

    var song = songs[i];

    var link = $('<a/>', {
        id: song.id,
        href: '#' + song.id,
        text: song.name,
        contextmenu: function(e){
            var contextMenu = new ContextMenu(song);
            contextMenu.show(e.pageY, e.pageX);

            //Prevent default context menu display.
            return false;
        }
    }).appendTo(listItem);
}

在这种情况下,当在 contextmenu 方法中访问歌曲时,歌曲将始终是 foreach 循环中迭代的最后一项。我想知道如何使链接与其定义歌曲之间存在 1:1 的关系。

我尝试将歌曲对象分配为链接对象的属性(通过 this.song 访问),但它显示为未定义。

4

2 回答 2

2
for (var i = 0; i < songs.length; i++){
    // note this
    (function(i) {
        var listItem = $('<li/>').appendTo(songList);

        var song = songs[i];

        var link = $('<a/>', {
            id: song.id,
            href: '#' + song.id,
            text: song.name,
            contextmenu: function(e){
                var contextMenu = new ContextMenu(song);
                contextMenu.show(e.pageY, e.pageX);

                //Prevent default context menu display.
                return false;
            }
        }).appendTo(listItem);
    // and this
    }(i));
}

请参阅此副本以获取解释。

于 2012-08-22T18:00:12.753 回答
2

另一个答案是更好的方法——将对象声明在for循环范围之外。但是,如果必须在 for 循环中声明对象,以下是解决问题的方法:

song从您的 contextMenu 函数声明了一级范围。因此,每当 contextMenu 执行时,它都会查找作用域链,直到找到变量,此时它总是会找到最后一个实例化的歌曲。您需要获取一份可用于 contextMenu 的歌曲副本,这也很棘手,因为对象在 JavaScript 中是通过引用传递的。您可以将自调用函数与 $.extend 结合使用来复制songnewSong在我的示例中重命名)并解决此问题:

for (var i = 0; i < songs.length; i++){
    var listItem = $('<li/>').appendTo(songList);

    var song = songs[i];

    var link = $('<a/>', {
        id: song.id,
        href: '#' + song.id,
        text: song.name,
        contextmenu: (function(song){
            var newSong = $.extend(true,{},song);
            return function(e) {
            var contextMenu = new ContextMenu(newSong);
            contextMenu.show(e.pageY, e.pageX);

            //Prevent default context menu display.
            return false;
          };
        })(song);
    }).appendTo(listItem);
}
于 2012-08-22T18:02:10.713 回答