1

I attempted to bind an object of events using a for key in object loop.

events = {
   mouseup:function(data){console.log(data)},
   mousedown:function(data){console.log(data)},
}
for (var key in events ) {
            console.log('binding: ' + key) ;
            $('body').on(key ,function(data){
                console.log(key ,data);
            })

}

However, the last object (mousedown) gets bound for both events. Could anyone explain why?

Check out the fiddle for a complete example.

https://jsfiddle.net/2439rw4a/

Megimoo
  • 387
  • 1
  • 3
  • 15

3 Answers3

2

Yeap - because key is not evaluated until the event fires, and by that time it has been overwritten and remains 'mousedown'.

You need to isolate the current value of key at the time of binding the event. You have two options:

1) Send it in via an immediately-executed function closure. This captures a local copy of key in the scope of the event callback.

for (var key in events ) {
    $('.box').on(key, (function(key) { return function(data){
        console.log(key);
    }; })(key));

2) Send it in via event data

for (var key in events ) {
    $('.box').on(key, {key: key}, function(evt){
        console.log(evt.data.key);
    });
Mitya
  • 33,629
  • 9
  • 60
  • 107
0

it's a good example of such bugs type.

You get such behaviour, because key in console.log(key) is equal to last key in for loop. All works fine, just change console log to show event type, not a key:

events = {
   mouseup:function(data){console.log(data)},
   mousedown:function(data){console.log(data)},
}
for (var key in events ) {
            console.log('binding: ' + key) ;
            $('.box').on(key ,function(data){
                console.log(event.type);
            })

}

jsfiddle: https://jsfiddle.net/2439rw4a/

Andrew Evt
  • 3,613
  • 1
  • 19
  • 35
0

By the time the event fires, the value of key is the last key. The execution of the code is similar to:

key = 'mouseup';

$('body').on(...);

key = 'mousedown';

$('body').on(...);

// By this time, key = 'mousedown'
// Mouse is clicked.
// When even fires, it looks for key which by now has the last key

Consider using Object.keys and array.forEach. This way, your handler sees key as the value at that iteration, instead of a shared key variable.

Object.keys(events).forEach(function(key){
  console.log('binding: ' + key) ;
  $('body').on(key ,function(data){
    console.log(key ,data);
  })
});
Joseph
  • 117,725
  • 30
  • 181
  • 234