'Vanilla Javascript use of bind() with REST parameter

Why bind() passes even the type of event with rest parameters. How to avoid passing the event 'click'?

function say(...numbers) {
  for (const number of numbers) {
    console.log(number);
  }
}

window.addEventListener('DOMContentLoaded', () => {
  const el = document.getElementById('input_10_5');
  el.addEventListener('click', say.bind(null, 1, 2, 3));
});

Console.log result:

1
2
3 
click { target: input#input_10_5.medium, buttons: 0, clientX: 1062, clientY: 732, layerX: 96, layerY: 24 

}



Solution 1:[1]

You can't. The event handling system always passes the event.

The callback function itself has the same parameters and return value as the handleEvent() method; that is, the callback accepts a single parameter: an object based on Event describing the event that has occurred, and it returns nothing.

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#the_event_listener_callback

If your goal is to iterate the arguments and treat them all the same then how about: function say(numbers, event) say.bind(null, [1, 2, 3])

Solution 2:[2]

This behavior doesn't have to do with rest parameters .... It is more to do with the behavior of .bind(). When you bind a function with arguments (in this case you've used 1, 2, 3), calling that bound function causes those bound arguments to be passed to the function first, then followed by any additional arguments you call the bound function with, eg:

function foo(one, two, three, evt) {
  console.log(one, two, three, evt);
}

const bar = foo.bind(null, 1, 2, 3);
bar({type: "click"}); // becomes the 4th argument (after 1, 2, 3)

Under the hood, JavaScript is calling your bound function that you pass to .addEventListener() with the event object, which ends up becoming the fourth argument to your say function. This is then included as part of the numbers array. You can instead create a wrapper function that gets passed event (which you ignore), and then use .call() to call your function (using .call() here instead of just () allows you to explicitly define the this value like you're doing with .bind()):

window.addEventListener('DOMContentLoaded', () => {
  const el = document.getElementById('input_10_5');
  el.addEventListener('click', () => say.call(null, 1, 2, 3));
});

Solution 3:[3]

Look at the documentation:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

You can't prevent bind from doing that.

If you don't want that, don't use bind.

Just create a new function the traditional way instead.

el.addEventListener('click', function () { say(1, 2, 3) });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Petr 'PePa' Pavel
Solution 2 aequalsb
Solution 3 aequalsb