ぷっぽプログラミング備忘録

linux, javascript, php, C#, そのうちScalaとかアプリ開発とかやってみたいです。

javascriptのforループ内のlet変数

forのインクリメントなどに使うletで定義した変数は、ループごとにスコープを持つ。

var examples = [];
for(let i=0; i<3; i++) {
  examples.push(() => console.log(i));
}
for (const elem of examples) {
  elem();
}

このiは、それぞれが独立したメモリ領域を持つとのこと。
従って、実行結果は

0
1
2

となる。
つまりは、こういうコードと同様の動作をする。

var examples = [];
for(let i=0; i<3; i++) {
  let _i2 = i;
  examples.push(() => console.log(_i2));
}
for (const elem of examples) {
  elem();
}

余談だが、 let i を var i に変えると

var examples = [];
for(var i=0; i<3; i++) {
  examples.push(() => console.log(i));
}
for (const elem of examples) {
  elem();
}

実行結果は

3
3
3

になる。(ループ終了判定時にiが3になるため)

混乱しやすいというか当然だが、

var examples = [];
let i=0;
for(; i<3; i++) {
  examples.push(() => console.log(i));
}
for (const elem of examples) {
  elem();
}

とletをループの外側で定義すれば、結果は

3
3
3

になる。

結論

var examples = [];
for(let i=0; i<3; i++) {
  examples.push(() => console.log(i));
}

var examples = [];
for(let i=0; i<3; i++) {
  let _i2 = i; // ※ここでiで書いていてもforループ内ではjavascript側で_i2がlet変数として用意され、ループ内でiと記述していた箇所が_i2に自動で置き換わって処理されるイメージ★あくまでイメージ★
  examples.push(() => console.log(_i2));
}

シンタックスシュガーのようなものということになるのかな。それで割り切っていこうというお話でした。

参考)https://teratail.com/questions/205789#reply-304154