Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

The following code is to generate bulletin board list. It works fine for viewing contents (eg, postId0, postId1, ...) but works as if 'i' were nPosts

I recall that in C# I had the same problem and fixed by declaring a copy of i (var copy_i = i; inside the loop), but here that didn't work either.

function loadList() {
    $.getJSON("list.php", function (json) {
        var nPosts = json.length;
        for (var i = 0; i < nPosts; i++) {
            var post = $('<ol/>', {
                class: "viewPost",
                id: "post" + i
            }).appendTo("#viewList");

            $('<li/>', {
                class: "viewPostId",
                id: "postId" + i,
                text: json[i].noteId
            }).appendTo("#post" + i);

            var memo = $('<li/>', {
                class: "viewMemo",
                id: "memo" + i,
                text: json[i].noteContent
            }).appendTo("#post" + i);

            //alerts 'nPosts' for every i.
            memo.on("click", function () { alert(i); });
        }
    });
}
share|improve this question
    
I'm reading through the code now, but as a preliminary question: are you familiar with the concept of closures (and how counter variables can also be closed over)? Usually questions about strange behavior in loops arise from neglecting closures. –  Asad Nov 26 '13 at 3:38

2 Answers 2

up vote 2 down vote accepted

As expected, the problem was with an unforeseen closure. This line:

memo.on("click", function () { alert(i); }); 

creates a closure over the i variable, which is incremented all the way to the maximum value before your click handler is ever invoked.

Here is how you would provide a "dummy variable" for your handler to close over:

var handlerCreator = function (counter) { 
    return function(){
        alert(counter); // The handler now closes over the counter variable, 
                        // which cannot be accessed by other code and therefore
                        // retains the value passed in to this function (i.e. the
                        // value of i on the current iteration)
    }; 
}
memo.on("click", handlerCreator(i));
share|improve this answer
    
Thanks! So the dummy variable method don't work in js and should always define function creator. I thought there might be some simpler workarounds. –  Jeffrey Goines Nov 26 '13 at 4:06

The click functionality that alerts i is executed after the loop is complete thus it will be equal to nPosts

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.