[Greasemonkey] addEventListener inside loop

Jeremy Dunck jdunck at gmail.com
Wed Feb 1 06:13:59 EST 2006


On 1/31/06, Daniel Hood <danhood at gmail.com> wrote:
> I'm have a bit of trouble with some code involving looping over some
> range and adding event listeners to elements.  It seems that the
> variables referenced in the anonymous function being bound to that
> event don't have the state of the loop variable at the time of
> binding, but rather the value once the loop has completed.  This is a
> much simplified case of the problem I am experiencing, but it
> illustrates the point.  I believe that this can be solved via a
> closure, but I don't seem to be having any luck.
>

Actually, you're creating a closure on accident, which is causing your
trouble.  :)

But you're doing well to understand the problems clearly.

Arvid's suggestion is good because it binds the current value of the
loop variable i to a local variable i in foo.

This would be clearer if he hadn't named the foo-local variable i.

> function do_stuff() {
>     for(i = 1; i <= 3; i++) {
>         document.getElementById("button" +
> i).addEventListener("click", function() { alert(i); }, false);
>     }
> }

So, when that anonymous function is created, JS stores the lexical
scope, which includes do_stuff, on the function object.  Later, when
you refer to i, JS climbs the scope chain and finds do_stuff.<var
obj>.i, which by then has the loop-exit value.

In Arvid's example (I'll change the param name):

function foo(K) {
   return function () {
      alert(K);
   }
}

button.addEventListener("click", foo(i), false);

What's going on here is the that loop variable's value is passed to
the local variable K, and the returned inner function then binds its K
to foo.<var obj>.K.

This does what you want because K is initially set to the value you
want,  and never changed.

  -Jeremy


More information about the Greasemonkey mailing list