Damn Vegetables
Damn Vegetables

Reputation: 12464

Loop, passing a function as a parameter, argument of that function is always the last one. How to use bind()?

I am trying to add an event handler to buttons which are generated in a browser extension. There are many buttons so it is done inside a loop, and the event handler of the button needs an argument (otherwise, all buttons will do the same thing).

for (....)
{
    ....
    var arg = createArgument(...);
    ....
    var myButton = document.createElement('button');
    myButton.addEventListner('click', function(){myButtonClick(arg)});
    ....
}

function myButtonClick(arg)
{

I used a method in this answer to pass an argument to the function, but the problem is that the arg for all buttons is set to the last value of arg at the last iteration of the for loop. A comment in that answer says that I have to use bind(), but I could understand how. In my case, how should I use bind() so that each button's event listener would have a different arg?

Upvotes: 0

Views: 44

Answers (2)

geekonaut
geekonaut

Reputation: 5954

You have two options here:

  1. Using a function to create a new scope and bind that scope to the current arg value
  2. Using bind to bind the current arg value as this inside the function

Here's how that works:

for (....) {
  ....
  var arg = createArgument(...);
  ....
  createButtonWithListener(arg);
  ....
}

function createButtonWitListener(arg) {
  var myButton = document.createElement('button');
  myButton.addEventListener('click', function(){ myButtonClick(arg) });
}

This works, because createListener gets called with the current value of arg and the value is copied into the scope of createListener.

The variation with using bind would bind this and the arguments inside the bound function to the values you pass, so it could work like this:

for (....) {
  ....
  var arg = createArgument(...);
  ....
  var myButton = document.createElement('button');
  myButton.addEventListener('click', function(boundArg){ myButtonClick(boundArg) }.bind(myButton, arg));
  ....
}

Upvotes: 0

Simone
Simone

Reputation: 53

The way to use bind is simply to call myButtonClick.bind(thisArg[, arg1[, arg2[, ...argN]]]): the first parameter is the value you want the function to refer to when you use the this keyword within the function and any other parameter after would be passed to the function as a normal argument.

In your case if you don't need to use this within your function you could simply do myButton.addEventListener('click', myButtonClick.bind(null, arg);

If you don't need to use your arg(s) outside of the loop and the functions I'd probably declare them as let arg rather than var that way they only appear within the loop.

Upvotes: 1

Related Questions