質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

2017閲覧

for文でのイベントリスナについて

meru53

総合スコア11

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2019/06/25 02:42

https://codezine.jp/article/detail/11353

上記のurlに書かれていた以下のコードで質問があります

javascript

1 2<ul> 3 <li>one</li> 4 <li>two</li> 5 <li>three</li> 6 <li>four</li> 7 <li>five</li> 8</ul> 9 10... 11<script type="javascript"> 12 var items = document.querySelectorAll('li'); 13 for (var i = 0; i < 5; i++) { 14 var li = items[i]; 15 li.addEventListener('click', function() { 16 alert(li.textContent + ':' + i); 17 }); 18 }; 19</script>

サイトの説明での、
イベントリスナはfor文の後に呼ばれる
というのは理解できました

ですが何故forの中で定義しているのにも関わらず、同じ値になるのでしょうか

ブラウザ内で実行されているイメージがつかめずモヤモヤしています。

超初心者な質問ですみませんが、どなたか補足説明をおねがいします。m(_ _)m

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

x_x

2019/06/25 05:26

type="javascript" ではそもそも動かないでしょうに。いい加減な記事ですねぇ
guest

回答4

0

こんな風にするとよいでしょう

javascript

1<script> 2window.addEventListener('DOMContentLoaded', function(e){ 3 [].forEach.call(document.querySelectorAll('li'),function(li,i){ 4 li.addEventListener('click', function() { 5 console.log(li.textContent + ':' + i); 6 }); 7 }); 8}); 9</script> 10 11<ul> 12 <li>one</li> 13 <li>two</li> 14 <li>three</li> 15 <li>four</li> 16 <li>five</li> 17</ul> 18

投稿2019/06/25 03:19

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meru53

2019/06/26 00:04

ありがとうございます。 まだ初心者で色んなソースを見る経験が浅いため、違う書き方はとても参考になります。
guest

0

ですが何故forの中で定義しているのにも関わらず、同じ値になるのでしょうか

varで宣言した場合、forで回す変数は全部同じ変数です。つまり、このコードは以下のように書くのと同じなのです。

javascript

1 var items = document.querySelectorAll('li'); 2 // ループと無関係に、同じ変数 3 var i = 0; 4 for (i = 0; i < 5; i++) { 5 var li = items[i]; 6 li.addEventListener('click', function() { 7 alert(li.textContent + ':' + i); 8 }); 9 };

ループを抜けきった後にはiは5となっていて、リスナーからは変化した後のiを参照することとなります。

投稿2019/06/25 02:46

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/06/25 02:47

なお、letで書いた場合はループ1回毎にスコープが取られるようになっていますので、このような問題は発生しません。
meru53

2019/06/26 00:15

ありがとうございます。 ループごとにスコープが取られるということがイメージできていなかったようです。
guest

0

ベストアンサー

この問題ですと、細かい動作としては以下のようになります。

変数iが値0で宣言される。

forループの1回目のイテレーションが実行される。

  • iは0、liは1つ目のリストアイテム。

forループの2回目のイテレーションが実行される。

  • iは1、liは2つ目のリストアイテム。

forループの3回目のイテレーションが実行される。

  • iは2、liは3つ目のリストアイテム。

forループの4回目のイテレーションが実行される。

  • iは3、liは4つ目のリストアイテム。

forループの5回目のイテレーションが実行される。

  • iは4、liは5つ目のリストアイテム。

iが5に加算されたところで、forループが終了する。

ここまでは元のサイトに書かれているとおりで、ポイントは最後にi=5になっているところです。
イベントリスナは、forが終わった後に実行されるのでイベントリスナ内に書かれている

alert(li.textContent + ':' + i);

に使われている「i」はforが終わったときに設定された「5」になっており、その後変化しないためにどこをクリックしても「5」が表示されます。

ポイントとしては、「変数は呼び出されたときに値が検証される」という事です。

「定義」と聞くとその時点で数値が確定するイメージがあるので少し混乱しますよね。

投稿2019/06/25 02:57

45_Shingo

総合スコア177

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meru53

2019/06/25 23:41

ポイントの部分がまさに自分が勘違いしていた所でした! cなどコンパイルする言語のイメージで考えていました。 ありがとうございました。
guest

0

変数がvarで定義されているので、変数iliの値が最後に設定された値になってしまっています。
変数をletで定義することでブロックスコープが作られるため、イメージしている通りの動きになるかと思います。

js

1var items = document.querySelectorAll('li'); 2for (let i = 0; i < 5; i++) { 3 let li = items[i]; 4 li.addEventListener('click', function() { 5 alert(li.textContent + ':' + i); 6 }); 7};

投稿2019/06/25 02:50

編集2019/06/25 04:06
ryo_y

総合スコア244

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2019/06/25 03:02

let のあとに変数名が抜け落ちてますね
meru53

2019/06/25 23:59

ありがとうございます ブロックスコープの違いによる説明でわかりやすかったらです。 ちなみにブロックスコープがそれぞれ作られるということは、letの変数だとループ回数分のエリアが確保されるということでしょうか。 (iが4バイトでループ回数1000回なら4k) 本来の質問からはそれてしまいますが、 その場合、スコープが解放されるタイミングも気になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問