Nathan Ridley
Nathan Ridley

Reputation: 34396

How am I misunderstanding JavaScript closure resolution in this example?

I thought I understood JavaScript closures but apparently I don't. Take the following excerpt from my code:

for(var i=0; i<data.List.length; i++) {
    var entry = data.List[i]; // I thought this line should have resolved the issue?
    $('<tr class="logs-list-item"><td class="lefticon nowrap"><a href="javascript:void(0)"></a></td><td class="right nowrap"></td></tr>')
        .appendTo(tbody)
        .find('a').text(entry.Text)
        .click(function() {
            alert(entry.Text + ' ' + entry.Filename);
            showLog(id, entry.Filename);
        })
        .closest('tr').find('td:last').text(entry.When);
}

As you can see, we're iterating through a list of filename entries and adding a table row for each entry with a bit of text describing the file and an onclick handler for each entry that is supposed to call a function showLog() with the details of the selected filename.

What is actually happening is that all of the rows are adding correctly but every one of them is being assigned a handler for the last item in the list.

On line #2 I am defining a variable inside the for loop and accessing that variable within the closure, but it ultimately doesn't seem to be resolving correctly when the function is actually called.

Any ideas what I'm doing wrong?

Upvotes: 1

Views: 141

Answers (3)

E.Beno&#238;t
E.Beno&#238;t

Reputation: 806

For this to work you need to use something like this:

for(var i=0; i<data.List.length; i++) {
    (function(entry){
        // your code goes here
    })( data.List[i] );
}

Upvotes: 2

ZeissS
ZeissS

Reputation: 12135

Can you try that code please?

function generateClickHandler(entry) {
  return function() {
    alert(entry.Text + ' ' + entry.Filename);
    showLog(id, entry.Filename);
  }
}


..click(generateClickHandler(entry))...

Upvotes: 0

SLaks
SLaks

Reputation: 887315

Javascript does not have block-level scoping.
Even though the variable is defined inside the loop, it's still shared.

You need to move the loop body to a separate function.

Upvotes: 4

Related Questions