8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

forループ内のaddEventListenerで詰まった

Last updated at Posted at 2019-07-03

・forループ内でのaddEventListener複数生成について

・forループ内でのaddEventListenerが動かない・・・
・【原因】スコープ問題
・【対処法】即時関数がいい
・おまけ DOMで習得できるelementの塊について

複数addEventListenerを作りたいけど動かないです。

やりたいこと→取得したtargetクラス(複数ある)の子要素に、クラスをつけ外ししたい。
書いたのがこちら。


var togList = document.getElementsByClassName('target');

for(var i = 0;i<togList.length;i++){
    togList[i].addEventListener('click',()=>{
    togList[i].firstElementChild.classList.toggle('pull');
    });
}

ちっとも動かない!

原因

スコープが問題だった。varで宣言された変数は関数内で参照が可能なので、
addEventListenerの値がループが終わり切ったiの値を参照指定していたのが問題。
→他の言語で出現するブロックスコープがないらしい。なんですって!(letを使えばブロックスコープが作れるとのこと)

【私がとった対処法】即時関数

**即時関数とは?
関数を定義し即時に実行される関数。これを使うことでスコープの汚染を防ぐことができます!

for(var i = 0;i<togList.length;i++){
   (function(n){
       togList[n].addEventListener('click',()=>{
           togList[n].firstElementChild.classList.toggle('pull');
       });

   })(i);
}

即時関数でラッピングして、それにiを渡しています。
これで一つ一つのaddEventListenerが正しいnを参照できますね。

【追記】
varではなくてletを使った方がいいかも。

おまけ DOMで習得できるelementの塊について

DOMでelementを習得する場合、getElementsByClassNameやquerySelectorAllなどは、elementの集合体を習得することになってしまいます。

この集合体は主に二種類の型があります。

HTMLCollection・・・
getElementsByClassName、getElementsByTagName、childrenなどで習得される。
動的なので、要素の増減がすぐに反映される。

NodeList・・・
querySelectorAllで習得される。
静的なので、要素の増減が即時に反映されない。

静的・動的の使い分けに気をつけなければならない。大変...!

8
8
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?