当lambda函数引用封闭循环中的变量时,javascript范围问题

javascript scope problem when lambda function refers to a variable in enclosing loop

关于stackoverflow的第一个问题:)希望我不会让自己难堪......

我有一个javascript函数,可以加载一个专辑列表,然后为每个专辑创建一个列表项。 列表项应该是可点击的,所以我用一个做东西的函数调用jQuery的click()。 我循环这样做。 我的问题是,所有项目似乎都获得了相同的点击功能,即使我尝试创建一个在每次迭代中执行不同内容的新项目。 另一种可能性是迭代变量以某种方式是全局的,并且函数引用它。 代码如下。 debug()只是Firebug的console.debug()的封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
function processAlbumList(data, c) {
 for (var album in data) {
  var newAlbum = $('<li class="albumLoader">' + data[album].title + '
</li>
'
).clone();
  var clickAlbum = function() {
   debug("contents:" + album);
  };
  debug("Album:" + album +"/" + data[album].title);
  $('.albumlist').append(newAlbum);
  $(newAlbum).click(clickAlbum);
 }
}

以下是上述函数运行时打印内容的记录,之后是单击不同项目导致的一些调试行。 它总是打印"10",这是专辑变量的最后一个值(有10张专辑)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Album: 0/Live on radio.electro-music.com
Album: 1/Doodles
Album: 2/Misc Stuff
Album: 3/Drawer Collection
Album: 4/Misc Electronic Stuff
Album: 5/Odds & Ends
Album: 6/Tumbler
Album: 7/Bakelit 32
Album: 8/Film
Album: 9/Bakelit
Album: 10/Slow Zoom/Atomic Heart
contents: 10
contents: 10
contents: 10
contents: 10
contents: 10

有任何想法吗? 把我推到墙上,这是。:)

/斯特凡


您需要引入另一个范围,例如:

1
2
3
4
5
var clickAlbum = (function (a) {
    return function () {
        debug("contents:" + a)
    };
})(album);


内部函数中的album变量是一个闭包,但是在声明每个函数时它的值不受约束。 这意味着每次循环时,album闭包都将更改为该循环中的值。 这里有更详细的解释

正如肖恩(和文章)所建议的,你可以通过改变变量的范围来解决这个问题。