Что будет в консоли и почему? (var заменён на let.)
let i = 10;let array = [];while (i--) { array.push(function () { return i + i; });}console.log([ array[0](), // ? array[1](), // ?]);
Ответ
[ -2, -2 ]
Оба колбэка возвращают -2. Все функции захватывают одну и ту же переменную i, а к моменту вызова цикл завершён и i === -1, поэтому i + i === -2.
Разбор
Почему let здесь не помогает
Per-iteration binding (новая привязка на каждой итерации) let создаёт только в заголовке цикла for (let i = ...; ...; ...). Здесь же let i объявлен снаружиwhile — это одна переменная на весь цикл, ровно как было бы с var. Все замыкания ссылаются на неё.
Шаг
i до i--
i после i--
Что пушится
1
10 (truthy)
9
fn (замыкание на общий i)
2
9 (truthy)
8
fn
…
…
…
…
10
1 (truthy)
0
fn
11
0 (falsy)
-1
цикл выходит
Условие while (i--) использует пост-декремент: проверяется текущее значение, затем i уменьшается. На итерации с i === 0 условие ложно, но i-- всё равно превращает i в -1.
Итого: в array 10 функций, и все возвращают -1 + -1 === -2.
Как получить разные значения
Захватить значение в локальную переменную на каждой итерации:
let i = 10;let array = [];while (i--) { const captured = i; // своя привязка на итерацию array.push(() => captured + captured);}// array[0]() === 18 (i было 9), array[1]() === 16 (i было 8), ...