1

I've noticed a difference between function and function() for addEventListener's callback. Which isn't a problem till I tried passing a parameter. Basically,

element.addEventListener("hover", logInput, false );
function logInput(){
    console.log('registered!');
}

works as intended, but adding parenthesis will cause it log immediately, without continual response to the event trigger:

element.addEventListener("hover", logInput(), false );
function logInput(){
    console.log('registered!');
}

Why is this? And how can I get it to work while passing a parameter such as:

element.addEventListener("hover", logOnInput(this), false );
function logOnInput(triggeredElement){
    console.log(triggeredElement);
}
House3272
  • 1,007
  • 5
  • 14
  • 29
  • 2
    Inside the click handler `this` will refer to the clicked element then why do you want to pass it as a parameter – Arun P Johny Feb 10 '16 at 04:06
  • 2
    `logInput()` will immediately invoke the method and will pass the value returned by it as the click handler, `undefined` in this case as there is no return value – Arun P Johny Feb 10 '16 at 04:07
  • bad example, but will the function have inherit the same scope as the callback? My issue was not with `this` but a variable in the same scope as the eventListener. – House3272 Feb 10 '16 at 04:09
  • 1
    The reason the parentheses after the function causes it to execute immediately, is that parentheses after a function causes it to execute immediately. –  Feb 10 '16 at 04:09
  • Does this answer your question? [addEventListener calls the function without me even asking it to](https://stackoverflow.com/questions/16310423/addeventlistener-calls-the-function-without-me-even-asking-it-to) – ggorlen Feb 16 '21 at 20:41

3 Answers3

4

(If you really want the triggered element, don't pass anything. this will automatically be set to the triggered element.)

element.addEventListener("hover", logOnInput, false);
function logOnInput(){
    console.log(this);
}

To answer your more general question...

There are a few ways to pass a function as an argument with certain arguments already set (this is referred to as "partial application"). If you are able to use modern JavaScript features, the simplest way is probably to use an arrow function.

element.addEventListener("hover", () => logOnInput(foo), false);
function logOnInput(message){
    console.log(message);
}

This will only work on very modern browsers. It won't work, for example, in IE 11. In order to support older browsers, you can use the longer form of a function expression.

element.addEventListener("hover", function() {logOnInput(foo);}, false);
function logOnInput(message){
    console.log(message);
}

Or you could define a separate function (won't work with this but will work with other variables).

element.addEventListener("hover", logFooOnInput, false);
function logOnInput(triggeredElement){
    console.log(triggeredElement);
}
function logFooOnInput() {
    logOnInput(foo);
}

Or you could use bind.

element.addEventListener("hover", logOnInput.bind(null, foo), false);
function logOnInput(message){
    console.log(message);
}
Nathan Wall
  • 6,426
  • 2
  • 22
  • 23
  • Would recommend `bind` in place of arrow functions in a browser environment. – Marty Feb 10 '16 at 04:11
  • For professional sites, yes, if you use arrow functions you need to use a transpiler. For personal sites you're coding for fun or for learning, I think using arrow functions should probably be fine at this point. – Nathan Wall Feb 10 '16 at 04:15
  • Yup, bind was exactly what I was looking for. Thanks! – House3272 Feb 10 '16 at 04:21
2

Its a javascript when you want to call a function you use parentheses. Without parentheses outside a function is useless. But inside a function as argument you use the function without the parentheses so that when that event occurs then only it would run. If you call a function using parentheses inside function argument it will be executed immediately and would also run when the event occurs. To call a function with its parameters inside a function and just to invoke in that event you need to use the bind method like below:

element.addEventListener("hover", logOnInput.bind(null, argument1, argument2, etc), false );

However, if you want to select the context as this then I would recommend you to use like this:

function logOnInput(elem,arguments) {
  //now you can use **elem** to refer **this**
}

And use the anonymous function for the hover event like this:

element.addEventListener("hover", function(){
   logOnInput(this,arguments)
}, false );
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
0

The bind function is probably the cleanest option if you are targeting on modern browsers only. Some blogs talk about the loss of performance comparing bind with anonymous functions. Some blogs talk bad about anonymous functions. On the anonymous function. All goes well passing arguments on the addEventListener. But when you get to removeEventListener passing the arguments won't work the same way as in the addEventListener. I found this dude, in 2005, with the answer: http://www.codingforums.com/dom-and-json-scripting/5909-how-pass-arguments-independently-using-addeventlistener.html

In resume, set your anonymous function to be equal to a newly declared "thing". Idk if this is a var or an expression. I tested var and it wont' work. Idk the technicalities of this at this point, but it works.

function addhoverIn(SELECTED) {
        SELECTED.addEventListener("mouseover", addHIn = function() { hoverIn(SELECTED); }, false);  
    }
function hoverIn(SELECTED) {
        SELECTED.removeEventListener("mouseover", addHIn, false);
    }
ffdigital
  • 11
  • 5