0

HTML:

<input type="button" id="hider" value="Click to hide">

Why this works:

JS:

function hide() {
   this.hidden=true;
};

hider.addEventListener('click',hide);

BUT, why this doesn't work:

hider.addEventListener('click', () => this.hidden=true);
HomoHabilis
  • 37
  • 1
  • 7

1 Answers1

1

Because this in your arrow function doesn't point to the <input> element. It points to the scope wherein the arrow function was created. Read about it on MDN.

EDIT: Answer to question in comments

In your case, if you want to use an arrow function in your event listener, just re-use the hider variable instead of this:

hider.addEventListener('click', () => {
  // use "hider" instead of "this"
  hider.hidden = true;
});

Taking it further

If you'd want to create an "element-agnostic" event handler, make it a higher order function that takes in the element to hide as a parameter and that returns an (here: anonymous) handler function. If this sounds cryptic to you, here's some example code:

const makeHideHandler = (element) => { // higher order function
  return () => {                       // event handler function
    element.hidden = true;             // action to perform
  };
};

With this, you can write a one liner to add the listener:

hider.addEventListener('click', makeHideHandler(hider));

If you want to know why it works, google for "closures".

However, the real strength of the higher order function approach becomes visible if you have more than one element that should hide the same (or other!) element(s). Consider the following:

Let's say, you have multiple buttons that, when pressed, should hide the same element. It's easy peas with makeHideHandler:

// grab all "button" elements
const hideButtons = document.querySelectorAll('.hide-button');
// grab the element to hide
const elemToHide = document.querySelector('.hide-me');

// make the handler, pass in the element that should be hidden
const hideHandler = makeHideHandler(elemToHide);

// add listeners to the buttons
hideButtons.forEach((button) => {
  button.addEventListener('click', hideHandler);
});

Or to create buttons that hide themself after pressing:

const hideButtons = document.querySelectorAll('.hide-button');
hideButtons.forEach((button) => {
  button.addEventListener('click', makeHideHandler(button)); // <-- pass in the button element
});
David
  • 3,552
  • 1
  • 13
  • 24
  • Thanks a lot. Kind of understand it, but just starting out JS and have huge chaos in my head right now. So, how would I do it with an arrow function inside the event listener? – HomoHabilis Oct 01 '20 at 15:11