Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 尝试在foreach循环中将变量传递到对象的方法构造函数时出现范围问题_Javascript_Jquery - Fatal编程技术网

Javascript 尝试在foreach循环中将变量传递到对象的方法构造函数时出现范围问题

Javascript 尝试在foreach循环中将变量传递到对象的方法构造函数时出现范围问题,javascript,jquery,Javascript,Jquery,我理解以下代码块中发生的情况,但不确定如何修复: 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: so

我理解以下代码块中发生的情况,但不确定如何修复:

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方法中访问song时,它将始终是foreach循环中迭代的最后一项。我想知道如何使链接和它们定义的歌曲之间有1:1的关系

我尝试将song对象指定为通过this.song访问的链接对象的属性,但结果显示为未定义

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));
}
请参阅以获取解释


请参阅以获取解释。

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

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

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);
}

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

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

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);
}

可能是重复的啊。你是对的,这是一个副本。不过,我在将逻辑扩展到我的应用程序时遇到了一些问题。我会摆弄它,如果我一分钟内弄明白了,我就把它关上!可能是重复的啊。你是对的,这是一个副本。不过,我在将逻辑扩展到我的应用程序时遇到了一些问题。我会摆弄它,如果我一分钟内弄明白了,我就把它关上!谢谢你。显然,闭包对我来说还是有点奇怪干杯,谢谢你。显然,闭包对我来说还是有点奇怪干杯。你的回答似乎同样有效,但我想我更喜欢用闭包的形式包装,而不是用这种方式创建副本。我想这只是个人偏好。我们的答案都使用闭包,但我只是想展示一个方法,如果引用范围外对象是一个需要$.extend的需求,那么您可以在其中解决这个问题。当然,在你的案例中,他的答案是更好的方法。你的答案似乎同样有效,但我认为我更喜欢用闭包的形式包装,而不是用这种方式创建副本。我想这只是个人偏好。我们的答案都使用闭包,但我只是想展示一个方法,如果引用范围外对象是一个需要$.extend的需求,那么您可以在其中解决这个问题。不过,可以肯定的是,他的答案是你最好的方法。