回答編集履歴

1

追記

2016/10/16 10:28

投稿

raccy
raccy

スコア21735

test CHANGED
@@ -45,3 +45,123 @@
45
45
  document.getElementById("demo").innerHTML = text;
46
46
 
47
47
  ```
48
+
49
+
50
+
51
+ ---
52
+
53
+ 【追記】
54
+
55
+
56
+
57
+ 1.の方はあまり言及してませんでした。letはブロックスコープです。ですので、ブロック内部に押し留まります。ちょっと例を書いてみます。
58
+
59
+
60
+
61
+ ```JavaScript
62
+
63
+ var list = [];
64
+
65
+ for (let i = 0; i < 10; i++) {
66
+
67
+ let x = i * 2;
68
+
69
+ list.push(function() {
70
+
71
+ console.log(i, x); // それぞれのループで i と x は異なる。
72
+
73
+ });
74
+
75
+ }
76
+
77
+ list[0](); // => 0 0
78
+
79
+ list[1](); // => 1 2
80
+
81
+ list[9](); // => 9 18
82
+
83
+ ```
84
+
85
+
86
+
87
+ このコードの`i`と`x`をみてください。これらはlet宣言のため、for文のブロックの中でのみ有効です。for文のブロックは10回繰り返しますが、それぞれのブロックは独立しており、そのため、`i`と`x`もそれぞれ10個作られます(ただし`i`は、次ループに行くときに以前の`i`の値を引き継ぎ、`i++`の処理をしてから別の`i`として作られることになります)。`list`に入れられた無名関数の中の`i`と`x`もそれぞれが独立していることになります。
88
+
89
+
90
+
91
+ もし、これらがvar出会った場合は、関数(この場合は関数がありませんので、全体の先頭)にあるものとみなされます。
92
+
93
+
94
+
95
+ ```JavaScript
96
+
97
+ var list = [];
98
+
99
+ for (var i = 0; i < 10; i++) {
100
+
101
+ var x = i * 2;
102
+
103
+ list.push(function() {
104
+
105
+ console.log(i, x); // 全体で一つの i と x しかないため、同じものになる。
106
+
107
+ });
108
+
109
+ }
110
+
111
+ list[0](); // => 10 18
112
+
113
+ list[1](); // => 10 18
114
+
115
+ list[9](); // => 10 18
116
+
117
+ ```
118
+
119
+
120
+
121
+ そのため、ブロック内部の`i`と`x`はそれぞれたった1個を十回のループで共通して使うようになります。こうなると`list`に入れていく無名関数の中の`i`と`x`は全て同じものを指すことになってしまいます。これでは同じ事になりません。
122
+
123
+
124
+
125
+ では、どうやって考えれば良いのか。それは、変数を**どのスコープ(範囲)で有効にしたいのか**です。varを使った場合、関数全体がスコープになり、関数全体でたった一つしかありません。新たな関数の中でさらにvarで宣言しない限り、常に同じものを指します。対して、letであればブロックの内側だけです。**もし、そのブロックがfor文やwhile文などのループであれば、それぞれのループの中で独立して存在することになります。**そのようなループで独立して使うには、別途何らかの関数を用意しない限り、varでは実現できません。他にも、各ブロックで同じ変数を使ってしまった場合の影響を避けるために、letを使うという手法があります。
126
+
127
+
128
+
129
+ 最後に、もし、letの場合をletを使わずに等価な形にした場合どうなるか、ですが、下記のようになります(変換にはBabelを使用)。
130
+
131
+
132
+
133
+ ```
134
+
135
+ "use strict";
136
+
137
+ var list = [];
138
+
139
+ var _loop = function _loop(i) {
140
+
141
+ var x = i * 2;
142
+
143
+ list.push(function () {
144
+
145
+ console.log(i, x); // それぞれのループで i と x は異なる。
146
+
147
+ });
148
+
149
+ };
150
+
151
+ for (var i = 0; i < 10; i++) {
152
+
153
+ _loop(i);
154
+
155
+ }
156
+
157
+ list[0](); // => 0 0
158
+
159
+ list[1](); // => 1 2
160
+
161
+ list[9](); // => 9 18
162
+
163
+ ```
164
+
165
+
166
+
167
+ _loop関数の`i`とfor文の`i`は異なる`i`です。_loop関数は10回呼び出されるため、`i`と`x`も10個作られると言うことがわかるかと思います。