Question:
What are the ways, and most importantly, how to correctly pass arguments to a function in an event handler
For instance:
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
, even this
, even null
, even вася
…. Next. The function code was originally:
function handler(event, bool) {
if(event.target.tagName == 'LI') {
var ul = menu.querySelector('ul');
if(bool) {
ul.style.backgroundColor = 'red';
} else {
ul.style.backgroundColor = '';
}
}
}
In this case, event
== undefined
, ul
== undefined
.
Added a line to the beginning of the function: event = event || window.event;
– event
appeared, rendered var ul = menu.querySelector('ul');
from the function began to work.
So what is the correct way to pass arguments?
Answer:
Use handler.bind(null, false)
With signature function handler(bool, event)
handler.bind(null, false)
will just return 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');
Or you can use a closure (if you don't need the 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, let's put it together:
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{}
is much better