What are the ways, and most importantly, how to correctly pass arguments to a function in an event handler
For example:

var menu = document.querySelector('.nav'); var ul = menu.querySelector('ul'); function handler(event, bool) { event = event || window.event; if(event.target.tagName == 'LI') { if(bool) { ul.style.backgroundColor = 'red'; } else { ul.style.backgroundColor = ''; } } } menu.addEventListener('mouseout',handler.bind(null, event, false), false); menu.addEventListener('mouseover',handler.bind(this, event, true), false); 

It seems to work, but there is no difference what context I pass to bind , at least this , at least null , at least вася .... Next. Initially, the function code was:

 function handler(event, bool) { if(event.target.tagName == 'LI') { var ul = menu.querySelector('ul'); if(bool) { ul.style.backgroundColor = 'red'; } else { ul.style.backgroundColor = ''; } } } 

At the same time event == undefined , ul == undefined .
Added a line to the beginning of the function: event = event || window.event; event = event || window.event; - event appeared, rendered var ul = menu.querySelector('ul'); from function began to work.
So how is it possible to pass arguments?

  • Whatever method you find, it will still be govnokod! Handlers are procedures that must accept only one property of type event. - user220409

3 answers 3

Use handler.bind(null, false)

With signature function handler(bool, event)

handler.bind(null, false) just returns a function with one argument for the event.

 function handler(bool, event) { console.log(bool, event); } let handleFalse = handler.bind(null, false); let handleTrue = handler.bind(null, true); handleFalse('Event 1'); handleTrue('Event 2'); 

Alternatively, you can use a closure (if you do not need this context):

 function getHandler(bool) { return function handler(event) { console.log(bool, event); } } let handleFalse = getHandler(false); let handleTrue = getHandler(true); handleFalse('Event 1'); handleTrue('Event 2'); 


Well, we will collect in a bunch:

 var menu = document.querySelector('.nav'); var ul = menu.querySelector('ul'); function handler(bool) { return function (event) { event = event || window.event; if(event.target.tagName == 'LI') { event.target.style.backgroundColor = bool ? 'red' : ''; } } } menu.addEventListener('mouseout',handler(false), false); menu.addEventListener('mouseover',handler(true), false); 
 <div class="nav"> <ul> <li>Item 1 <li>Item 2 <li>Item 3 <li>Item 4 </ul> </div> 

Although, in my opinion, .nav li:hover{} much better

  • don't bind here - Grundy
  • if this context is not needed, the context is lost in all solutions. And, by the way, in the second case it will at least be equal to the element to which the subscription goes - Grundy
  • @Grundy, you're carping. Obviously, if the author needs a context, instead of null in bind, he will write the menu - vp_arth
  • Obviously, if the author knew that it was possible, he would not have asked a question here. In addition, answers are read by other users other than the author, who are not at all familiar with the work of bind, and how events work - Grundy
  • those. There are no other options, except how to use intermediate variables? - pepel_xD

In order for the context to have a value, you need to explicitly use this in the handler function.

The first parameter in bind to pass the object that you would like to see as this .

I will use the @vp_arth spippet.

 var menu = document.querySelector('.nav'); function handler(bool, event) { event = event || window.event; if(event.target.tagName == 'LI') { // в оригинале красится весь список, поступим так же this.querySelector('ul') .style.backgroundColor = bool ? 'red' : ''; } } menu.addEventListener('mouseout',handler.bind(menu, false), false); menu.addEventListener('mouseover',handler.bind(menu, true), false); 
 <div class="nav"> <ul> <li>Item 1 <li>Item 2 <li>Item 3 <li>Item 4 </ul> </div> 

Note that in the handler.bind(menu, false) handler handler.bind(menu, false) this === menu , and bool === false .


Consider what the error of your code.

handler.bind(null, event, false) - you create a function here and now, associating:

  • null as this ,
  • global event variable as the first parameter (at this stage it is equal to undefined )
  • false as second parameter

As a result, when an event occurs, the handler(undefined, false, event) is called in the context of null (that is, without context), the results of which you have seen.

  • Indeed, I missed the question. =) - vp_arth
  • There it is, that is when I passed to bind anything other than the menu , and at the same time, the ul sample was in a function, he honestly told me that inside this object there is no element with such a selector. But wait, I had var ul = menu.querySelector('ul') , i.e. In any case, he should have turned to the global menu , right? - pepel_xD
  • in the context of null (that is, without context) - in fact the global object will be used, in this case, window - Grundy
  • one
    @Grundy, this is without use strict - user236014
  • And yet, event in the function declaration was made the last argument, let the arguments be a dozen, it is still the last, as optional, as the line says: event = event || window.event; event = event || window.event; and we don’t pass it to bind , since this object is received only when an event occurs. And if in the future it will be necessary to remove the handler, it is necessary to use intermediate variables. As event with the handler bound through bind cannot be deleted. - pepel_xD

 var btn = document.getElementById("btn"); var theVal = "спасибо за минус дружище )-"; btn.addEventListener("click", function(event, str = theVal){ alert(str); }); 
 <button id="btn">click</button> 

one function for two events with different parameters

 function work(str){ document.getElementById("btn").innerHTML = str; } btn.addEventListener("mouseover", function (event, str = 'спасибо за минусы'){ work(str); }); btn.addEventListener("mouseout", function (event, str = 'и одному человеку за плюс ✌'){ work(str); }); 
 <div id="btn">click</div> 

  • Comments are not intended for extended discussion; conversation moved to chat . - Nicolas Chabanovsky