[HOW TO] pass parameter to a addEventListener function

Jul 13, 2023 | Read time 9 minutes

🔔 Table of contents

Introduction

One common request that I have noticed while working with addEventListener is how do we pass parameters to the handler event.

Now if we look at the syntax for addEventListener we can see that it only accepts a function reference.

addEventListener(event type, listener, options)

  • event type is a string of a “event type” and case-sensitive. So this means that ‘Click’ (and will not work) is different to ‘click’. You can see all possible event types here: Events
  • listener is a function reference.

A common way to use “addEventListener” is as follows:

    let button = document.querySelector('#myButton');
    button.addEventListener('click', function() {
        console.log('Button clicked!');
    });

So what if we want to give some parameters to the listener function. For example, when a user “click” on a element, we want to call the listener function but also give it some dynamic parameters (eg counts, constants, etc).

A common mistake that I see people doing is as follows:

   

    let button = document.querySelector('#myButton');
    button.addEventListener('click', doSomething(x,y));

Now the above is not correct since when we call doSomething(x,y) In this post I will outline the possible ways we can do this. Generally to pass parameters to the addEventListener listener function we have the options:

  1. Use anonymous functions
  2. Use the bind() method
  3. Using arrow functions
  4. Use function currying

1. Use anonymous functions

One way to be able to pass a parameter to your addEventListener function is to first wrap it around anonymous function.

For example:

let greeting = 'Hello, world!';

element.addEventListener('click', function(event) {
  doSomething(event, greeting);
});

function doSomething(event, greeting) {
  console.log(greeting);
  // do more stuff here
}

In this case, the anonymous function is the actual event listener, and it’s calling “doSomething” function with the extra parameters you need.

Now we can see that the “greeting” variable can be passed. This is usually how I would approach this problem.

Tip: there are downsides to using anonymous functions

The use of anonymous functions with addEventListener() can be very useful and is a common practice in JavaScript programming.

However, there are several potential disadvantages:

  • removeEventListener() - When you use an anonymous function as an event handler, you won’t be able to easily remove it with removeEventListener().

The removeEventListener() method requires a reference to the exact function passed into addEventListener(). This will not be available when an anonymous function is used.

  • Performance issues - every time we call the code that attaches the event listener is run, a new function (the anonymous function) has to be created.

This can cause problems when you are running performance sensitive applications - for example adding hundreds and thousands of event listeners.

Consider techniques such as “event delegation” if this is the case.

2. Use the bind() method

An alternative way to pass parameters to the addEventHandler listener function is to use the bind() method.

Generally the syntax for the bind() method looks like this:

bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, arg2, /* …, */ argN)

The bind() method just returns a new function with extra arguments you want to pass into the old function.

Note: The first argument of the bind method has to be the this value

So to apply this to our addEventHandler - consider the following JavaScript:

let greeting = 'Hello, world!';

element.addEventListener('click', doSomething.bind(null, greeting));

function doSomething(greeting, event) {
  console.log(greeting);
}

In this case, bind() is creating a new function from doSomething. The first parameter is “null” since we do not need to do anything with the this object.

The second parameter is our actual “greeting” parameter.

Keep in mind that the event object in the doSomething will be the second argument when using bind(), because any bound parameters are prepended to the arguments.

In the above example, ‘Hello, world!’ would be logged to the console when the element is clicked.

3. Using arrow functions

Similar to the anonymous function option, we can use the new JavaScript feature of arrow functions.

Using arrow functions we can make our code even shorter if there’s only one parameter or one line of code within the function.

To pass a parameter to an event listener using an arrow function, you can do:

let greeting = 'Hello, world!';

element.addEventListener('click', (event) => doSomething(event, greeting));

function doSomething(event, myParameter) {
  console.log(myParameter);
}

In this case, the arrow function is the event listener, and it’s calling myFunction with the event object and the extra parameter.

Whats the benefit of using arrow functions?

Introduced in ECMAScript 6 (ES6) as part of the 2015 JavaScript update, arrow functions bring several benefits to the table, from terser syntax to new ways of handling this keyword.

Arrow functions and the this keyword

Beyond their syntactic sugar, arrow functions behave differently from traditional functions when it comes to the this keyword. In JavaScript, this refers to the object that the function is a method of.

However, the value of this can be notoriously tricky to manage in traditional functions, as it changes depending on the context in which the function is called.

Arrow functions, however, capture the value of this from the enclosing context where the arrow function is defined, a behavior known as lexical scoping. This can make your code much easier to reason about:

function Person() {
    this.age = 0;

    setInterval(() => {
        this.age++; // `this` properly refers to the person object
    }, 1000);
}

In the example above, the arrow function allows this.age++ to correctly refer to the Person object, something a traditional function would struggle with.

4. Use function currying

Another option we can take to pass parameters to the the addEventListener function is using function currying.

Generally what this means is that in our “handler” function, we just return another function that accepts the same parameters:

let button = document.querySelector('button');

let myParam = 'Hello, World!';

button.addEventListener('click', doSomething(myParam));

function doSomething(param) {
    return function() {
        console.log(param);
    }
}

In this example, myFunction(myParam) is immediately invoked and returns a new function.

Now the function that we returned will have access to the outer function’s variables, including “param”, because it creates a closure over “param”.

So when someone clicks the button, the click event fires, it calls this returned function. This will have access to “param”.

What the heck is function currying??

The name might through you off, but function currying is simply a function returning another function.

Commonly, it is used used to break down a function with many arguments into a smaller functions with only one argument.

We create a function that takes the first argument and returns a new function that takes the next argument, and so on.

Consider a function multiply(a, b, c) that takes three arguments.

function multiply(a, b, c) {
    return a * b * c;
}

Here’s how we can curry it:

function curryMultiply(a) {
    return function(b) {
        return function(c) {
            return a * b * c;
        }
    }
}

Now we can use it as follows:

console.log(curryMultiply(2)(3)(4));  // Outputs: 24

So instead of passing in the same variables over and over with our original multiply function - eg:

multiply(2, 3, 4)

We can do this:

curryMultiply(2)(3)(4)

Summary

A common question when working with addEventListener is that we need to pass in parameters to the function handler.

Now this can be a problem when addEventListener only accepts a function reference and not a function CALL.

The common mistake is to call the function that is similar to:

addEventListener('click', doSomething()) - notice the parentheses - this will result in a function call.

Generally to pass parameters to the addEventListener listener function we have the options of:

  1. Use anonymous functions to wrap our code and have another function to execute with parameters
  2. Use the bind() method to bind the parameters to the handler function
  3. Using arrow functions
  4. Use function currying - we call a function that returns a function with the parameter

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube