3

I have the following:

 for (var i = 0; i <= 10; i += 1) {

    var $page_button = $('<a>', {
        html : i,
        click : function () {

            var index = i;
            console.log(index);
            return false;
        }
    });

    $page_button.appendTo($wrapper);
}

I thought that var index would be defined separately for each iteration of the loop because it is enclosed within a function. In this case the value of index that is printed is always 10.

The link text is the correct value of i, because this is written to the DOM and is then immutable .

Why is this, and what should I change to fix my problem?

I know this is similar to lots of other questions but the behaviour of using this notation is causing a different result. I am using jQuery 1.7.2 (Can't use any newer unfortunately.)

4 Answers 4

4

You need to enclose that in a closure to solve the problem..

var $page_button = $('<a>', {
        html : i,
        click : (function (num) {
           return function(){
               var index = num;
               console.log(index);
               return false;
            }
        })(i)
    });
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant - I was getting frustrated when this wouldn't work but I hadn't seen the self-calling part at the end. Works well - thank you.
2

A reference to i is closed up as part of the anonymous function. Note: not to its value, but a reference to i itself. When the function is run, the value is evaluated. Because the function runs after the loop has ended, the value will always be the last value of i. To pass just the value around, you do something like this:

    click : (function (index) {
        return function () {
            console.log(index);
            return false;
        };
    })(i)

You create an anonymous function which you execute immediately, which takes a value as argument and returns your actual function.

Comments

0

The variable index is defined separately for each execution of the function, but you copy the value from the variable i inside the function, so you will use the value of i as it is when the function runs, not when the function is created.

You need a function that is executed inside the loop to capture the value of the variable:

for (var i = 0; i <= 10; i += 1) {

  (function(){
    var index = i;

    var $page_button = $('<a>', {
      html : i,
      click : function () {
        console.log(index);
        return false;
      }
    });

  })();

  $page_button.appendTo($wrapper);
}

Comments

0

Every handler is sharing the same i variable. Each one needs its own variable scope in order to reference a unique index.

 for (var i = 0; i <= 10; i += 1) {
    var $page_button = $('<a>', {
        html : i,
        click : makeHandler(i)  // invoke makeHandler, which returns a function
    });
    $page_button.appendTo($wrapper);
}

function makeHandler(index) {
    return function () {
                console.log(index);
                return false;
           };
}

Here I made a makeHandler function that accepts the index argument, and returns a function that is used as the handler.

Because a function invocation sets up a new variable scope, and because a function is created and returned inside the makeHandler, each handler returned will reference its own scoped index number.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.