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>