Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

317
Views
Why addEventListener works unexpected on element remove?

$lis = document.getElementsByTagName('li');

for (let i = 0; i < $lis.length; i++) {
  $li = $lis[i];
  $span = $li.getElementsByTagName('span')[0];
  $button = $li.getElementsByTagName('button')[0];

  $button.addEventListener('click', $li.remove);
}
<ul>
  <li>
    <span>1</span>
    <button>x</button>
  </li>
</ul>

On the last line I'm using Element.remove() method, but instead of deleting the <li> it deletes <button>.

Explain to me, please, why. I feel that there is something with this happening, but I want to understand this completely not just feel.

P.S. I also understand that I can solve this by wrapping the $li.remove in an anonymous function, but the point of my question is to understand described behaviour not just to solve the problem. Thanks.

about 4 years ago · Santiago Trujillo
2 answers
Answer question

0

In this line $button.addEventListener('click', $li.remove); you are passing the $li's remove method as your click handler. The nature of click handlers (and other user-event handlers) is to rebind this in the handler function to the element you attach the listener to, so what really happens is

$li.remove.call($button)

You can fix it using bind:

$button.addEventListener('click', $li.remove.bind($li))

Sidenote:

Replace the live HTMLCollection document.getElementsByTagName('li') with a static NodeList by using document.querySelectorAll('li').

Removing an element from the DOM will also immediately remove it from any HTMLCollection it is part of, messing up your indexes.

about 4 years ago · Santiago Trujillo Report

0

It's because the button because the new context or this that Element.remove() is called with. An anyonmous function, or more accurately, an arrow function, uses the lexical scope that it's declared in as the context, that's why it works.

So button.addEventListener('click', elementX.remove) actually takes the prototype function remove and calls it with the button as the context or in other words, it binds it to the button.

A way to demonstrate binding can work, is by binding remove to the element, then adding it as the event handler $li.remove.bind($li) this way, regardless of the implicit context, we've explicitly set it to $li.

$lis = document.getElementsByTagName('li');

for (let i = 0; i < $lis.length; i++) {
    $li = $lis[i];
    $span = $li.getElementsByTagName('span')[0];
    $button = $li.getElementsByTagName('button')[0];
    let remove = $li.remove.bind($li)

    $button.addEventListener('click', remove);
}
<ul>
  <li>
    <span>1</span>
    <button>x</button>
  </li>
</ul>

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!