javascript scope problem when lambda function refe

2019-01-20 09:16发布

问题:

First question on stackoverflow :) Hope I won't embarrass myself...

I have a javascript function that loads a list of albums and then it creates a list item for each album. The list item should be clickable, so I call jQuery's click() with a function that does stuff. I do this in a loop. My problem is that all items seem to get the same click function, even though I try to make a new one that does different stuff in each iteration. Another possibility is that the iteration variable is global somehow, and the function refers to it. Code below. debug() is just an encapsulation of Firebug's console.debug().

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

Here is a transcript of what it prints when the above function runs, after that are some debug lines caused by me clicking on different items. It always prints "10", which is the last value that the album variable takes (there are 10 albums).

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

Any ideas? Driving me up the wall, this is. :)

/Stefan

回答1:

You need to introduce another scope, such as like this:

var clickAlbum = (function (a) {
    return function () {
        debug("contents: " + a)
    };
})(album);


回答2:

The album variable in your inner function is a closure, however its value is not bound when each function is declared. That means that each time through the loop, the album closure will be changed to the value it has in that loop. There is a more detailed explanation here

As Sean (and the article) suggest, you can solve this problem by changing the scope of the variable.