admin管理员组

文章数量:1332395

Let's say I have a function taking two arguments, like this:

function displaySum(a, b) {
    this.textContent = a + b;
}

I also have a button:

<button id="my-button"></button>

I would like to make a sum() function my event listener, but passing a and b exclusively. I know it can be done this way:

document.getElementById('my-button').addEventListener(sum.bind(null, 3, 7));

The problem is that this is lost that way. I tried setting it to null or undefined and hope that it says ignore this and let others inject their this, but instead it sets this to undefined or null in strict mode and to Window in non-strict mode. Is it possible to keep the event target as this after binding?

Disclaimer: I'm asking for educational purpose, not looking for other ways to achieve the same result, as I know them.

Let's say I have a function taking two arguments, like this:

function displaySum(a, b) {
    this.textContent = a + b;
}

I also have a button:

<button id="my-button"></button>

I would like to make a sum() function my event listener, but passing a and b exclusively. I know it can be done this way:

document.getElementById('my-button').addEventListener(sum.bind(null, 3, 7));

The problem is that this is lost that way. I tried setting it to null or undefined and hope that it says ignore this and let others inject their this, but instead it sets this to undefined or null in strict mode and to Window in non-strict mode. Is it possible to keep the event target as this after binding?

Disclaimer: I'm asking for educational purpose, not looking for other ways to achieve the same result, as I know them.

Share Improve this question asked Jun 9, 2019 at 11:34 Robo RobokRobo Robok 22.8k20 gold badges83 silver badges141 bronze badges 4
  • Bind, call and apply are the only functions in JS that can modify context on functions. Is there a specific reason you want to use this inside the calculation function? Doesn't look like something I'd use in a real world application. – Albert Commented Jun 9, 2019 at 12:19
  • 1 Obviously it’s not a real-world example, but I have needed to pass arguments to an event callback a few times in the past. I did it using an anonymous function as a wrapper back then. My inner perfectionist was curious if there is another way. – Robo Robok Commented Jun 9, 2019 at 12:22
  • I see. I've wondered this a few times myself as well, but I came to the conclusion that a concise arrow function wrapper is the best practice for me. Separating the calculation logic from modifying the DOM is always a good idea anyways, adhering to the OOP philosophy, so it's probably for the best this way. – Albert Commented Jun 9, 2019 at 12:47
  • I prefer to use a non-arrow function in this case to be honest. Instead of injecting event.target manually, I prefer to use the value passed to this by the browser. I know they are equal, but anyway it's one of a few cases where I avoid arrow functions. I do love them in most of other cases. – Robo Robok Commented Jun 9, 2019 at 12:50
Add a ment  | 

2 Answers 2

Reset to default 4

A couple of approaches to this:

First, pass the target element as the first argument to bind():

let el = document.getElementById('my-button');
el.addEventListener('click', sum.bind(el, 3, 7));

or

document.getElementById('my-button').addEventListener('click', evt => sum.call(evt.target, 3, 7));

Second, use an anonymous function to retain scope:

document.getElementById('my-button').addEventListener('click', function() { sum.call(this, 3, 7) });

Well you can always use an assigner function declared beforehand to reduce hard coding, that way you don't need to explicitly pass anything. For example:

const missingText = event => event.target.innerText = 'Missing parameters';

If you want to assign dynamic value you can use a generator pattern as well:

const sum = (a, b) => a + b;

const setSum = (a, b) => (event) => event.target.innerText = sum(a, b);

document.querySelector('#my-button').addEventListener('click', setSum(3, 7));

Might look a bit daunting if you're not familiar with the generator pattern, but in my opinion it's much cleaner, less and more readable code, and no binding required.

本文标签: javascriptBind event listener and keep element as thisStack Overflow