1

I have an array of objects that define aspects of some buttons, including a name and a callback function that is intended to be used as an on-click callback.

The idea is to iterate the array of objects, and wire up details from each object to its button, including the callback function.

However, a click on any button shows that the name & final callback from the final object in the array are used for all of the buttons.

The example snippet uses 2 buttons as that is all that is needed for a clear repro.

I get that there is a scoping issue happening here and that the value of i is assessed at runtime of the callback, not at the time of setting the event listener. That can be fixed with a generator function that re-scopes i. However, what is the approach to handling the callback functions which cannot be passed by value / copied?

function cb1(s){ console.log('cb1: I am ' + s); };
function cb2(s){ console.log('cb2: I am ' + s); };


var a = [ 
          {name: 'object 1', fn: cb1}, 
          {name: 'object 2', fn: cb2} 
          ];

for (var i = 0, max = a.length; i < max; i = i + 1){

    var btn = $('#b' + i); 
    var m = a[i];
    btn.on('click', function(e){ m.fn(m.name); } );

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id='b0'>Button 1</button>
<button id='b1'>Button 2</button>

EDIT: Fixed snippet button id's and this syntax error

var btn = $('#b' + [i]); should be $('#b' + i);

A solution using let has been proposed, however, this fails too - see snippet below.

function cb1(s){ console.log('cb1: I am ' + s); };
function cb2(s){ console.log('cb2: I am ' + s); };


var a = [ 
          {name: 'object 1', fn: cb1}, 
          {name: 'object 2', fn: cb2} 
          ];

for (let i = 0, max = a.length; i < max; i = i + 1){

    var btn = $('#b' + i); 
    var m = a[i];
    btn.on('click', function(e){ console.log('i = ' + i); m.fn(m.name); } );

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <button id='b0'>Button 1</button>
    <button id='b1'>Button 2</button>
Vanquished Wombat
  • 9,075
  • 5
  • 28
  • 67

0 Answers0