Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

313
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda