Когда я выполнил этот код, я ожидал увидеть 100 записанных в консоли 10 раз (исходя из опыта использования других языков):
const arr = [];
for (let i = 0; i < 10; i++)
arr.push(() => i * i);
arr.forEach(f => console.log(f()));
Но я получаю квадрат каждого числа (от 0 до 9). Это, кажется, ведет себя иначе, чем в некоторых других языках.
Например, используя C # , вы получите 100 десять раз:
var list = new List<Func<int>>();
for(var i = 0; i < 10; i++)
list.Add(() => i * i);
list.ForEach(f => Console.WriteLine(f()));
Python печатает 81 десять раз:
arr = []
for i in range(10):
arr.append(lambda: i * i)
for f in arr:
print(f())
Java не допускает этого, поскольку захваченные переменные не могут изменяться.
См. this для примеров на других языках.
Как объяснил Марк ниже, когда мы используем let (область видимости блока) в JavaScript, значение i фиксируется в новой переменной области действия в каждой анонимной функции. Когда вы посмотрите на фактическое определение каждой функции (используя: arr.forEach (f => console.dir (f)); ), вы увидите, что есть область действия (_loop), из которой значение i фиксируется на каждой итерации:
[[Scopes]]: Scopes[3]
0: Closure (_loop) {i: 0}
[[Scopes]]: Scopes[3]
0: Closure (_loop) {i: 1}
and so on...
Если мы повторно запустим этот пример, используя var , неудивительно, что область действия уровня блока _loop отсутствует, и вместо этого я сохраняется в области уровня модуля / файла с тем же значением (10) для каждого итерация:
[[Scopes]]: Scopes[2]
0: Closure (./src/index.js) {i: 10}