2

It is simple: I need to register an event property with a function. But in order to pass arguments to the function, I create a closure.

var x=0

function foo(bar1,bar2){
    return function (){
        alert (bar1+bar2);
        x++;   
    }   
}

for (var i=0;i<document.getElementsByTagName("div").length;i++) {
    document.getElementsByTagName("div")[i].onclick=foo(x,i)
}

Since I have 5 div elements, and I thought it should alert like this if I click all the div from top to down:

0
2
4
6
8

but instead it output:

0
1
2
3
4

It seems like that every time in foo(x,i), x is equal to 0. How do I get foo() to access the new value of x instead of its first initiation?

3
  • 1
    You're incrementing x but not using it in the addition in the function. JavaScript always passes by value, so when you did foo(x,i); it made a copy of the value 0. If you want the handler to use the current state of x, then don't pass x to foo(). Just pass i, and inside the handler do alert(x + bar1);. jsFiddle DEMO Commented May 7, 2014 at 14:47
  • @cookiemonster You should have posted that as an answer. I didn't see your comment and now my answer is basically the same as your comment. Commented May 7, 2014 at 14:56
  • @JamesMontagne: That's alright. +1 on your answer. Commented May 7, 2014 at 14:59

2 Answers 2

1

You are incrementing x only within the inner function. This function is only called once an element is clicked. As a result, at the time foo is called, x is always 0. It is only incremented later when something is clicked and at that point the values of bar1 are already set (to 0).

You could do something like this instead:

var x=0

function foo(bar1){
    return function (){
        alert (bar1+x);
        x++;   
    }   
}

for (var i=0;i<document.getElementsByTagName("div").length;i++) {
    document.getElementsByTagName("div")[i].onclick=foo(i)
}

In this way you will always use the current value of x instead of the value at the time foo was called.

Sign up to request clarification or add additional context in comments.

6 Comments

you should try running your code in a jsfiddle before you answer a question.
Can I let the x increment before returning the inner function?
lol in your code, try clicking the same div more than once, and see if that don't mess up everything... It works just fine if you click one at a time.
@user3448456 When you increment all depends on when you want x to increase. If you want it to increase every time something is clicked, then the code in my answer is correct. If you want x to be locked in as 1, 2, 3, etc. then you can use your previous code but increment x before calling foo.
@JayHarris All depends how you interpret the intent of the original code.
|
0

You need to increment x where you increment i. Because on every iteration x is still zero thus the values you're getting 0,1,2,3,4 are actually the values of i.

In your code, you are passing the value 0 to the variable bar1 on every iteration and the only time that x increments is after you click the button not during the iteration, so if you put another alert for x in front of this alert alert (bar1+bar2); you see what i mean.

Finally to increase x on every iteration you must explicitly do it in the loop. like this:

;i++, x++)

JSFIDDLE

This would output 0,2,4,6,8 without increment x on every click.

    var x   = 0,
        div = document.getElementsByTagName("div");

    function foo(b1, b2){
        return function () {
          alert (b1 + b2);
        }            
    }

    for (var i = 0; i< div.length; i++, x++) {
        div[i].onclick = foo(x, i);
    }

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.