・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で習得される。
静的なので、要素の増減が即時に反映されない。
静的・動的の使い分けに気をつけなければならない。大変...!