Event delegation by parsing lines in a for loop

Possible duplicate:
Closing Javascript Inside Loops - A Simple Practical Example

I recently played with some more complex aspects of JavaScript, one of which is design patterns and delegation.

I created an object containing 2 keys, which then process and attach the event to the body.

My problem is that the last function seems to be bound for any iteration of the for loop. I am sure this is a copy of the link / area definition (thanks Schmiddti), but please correct me if I am wrong.

Is there a way to fix my problem, to attach 2 events at the proper level without changing too much? (Since this is a complex application that I have simplified to this problem).

For a jsfiddle example, see how the warning message for .div1 matches .div2

 var foo = { init: function() { var i = 0, keys = [] self = this; for (var key in this) { keys.push(key); } for (i; i < keys.length; i++) { if (keys[i].match(/^on/i)) { var delegateFunc = keys[i].split(' | '), event = delegateFunc[2], selector = delegateFunc[1], keyName = keys[i]; console.log('###'); console.log( 'selector: ' + selector ); console.log( 'event: ' + event ); console.log( 'function: ' + self[keyName] ); $('body').on(event, selector, function(ev) { self[keyName](ev, ev.target); }); } } }, 'on | .div1 | click': function(ev, el) { alert('you clicked 1'); }, 'on | .div2 | click': function(ev, el) { alert('you clicked 2'); } } $(function() { foo.init(); });​ 

Do you need more information? Leave me a comment. Greetings

+4
source share
3 answers
  $('body').on(event, selector, function(ev) { self[keyName](ev, ev.target); }); 

replace it with the following code:

  (function(keyName) { $('body').on(event, selector, function(ev) { self[keyName](ev, ev.target); }); })(keyName); 

The reason for this is because JavaScript does not have a block area. So your var keyName is the same variable in every loop, and closing your callback function binds the variable, not the value it has at that moment. That way, once the loop finishes, the variable will be what its last value was in all of your callback functions.

By adding an immediately executed function that takes keyName as an argument, you create a new variable (function argument) and thereby avoid the problem.

+2
source

The classic closure problem.

Put the for loop in the function expression immediately called

 for (i; i < keys.length; i++) { (function(lockedIndex) { if (keys[lockedIndex].match(/^on/i)) { var delegateFunc = keys[lockedIndex].split(' | '), event = delegateFunc[2], selector = delegateFunc[1], keyName = keys[lockedIndex]; console.log('###'); console.log('selector: ' + selector); console.log('event: ' + event); console.log('function: ' + self[keyName]); $('body').on(event, selector, function(ev) { self[keyName](ev, ev.target); }); } })(i) } 

Check script

+1
source

keyName expires by the time your event handler starts, you need to wrap it in a new area:

 (function(key) { $('body').on(event, selector, function(ev) { self[key](ev, ev.target); }); })(keyName); 
0
source

All Articles