Потому что замыкание в JavaScript захватывает саму переменную, а не её значение в момент создания функции. В вашем коде `var` даёт одну общую переменную `i` для всего цикла; после выхода из цикла `i` становится 333, и все сохранённые функции при вызове читают текущее значение переменной — поэтому `funcs[0]()` выведет 333. Как сохранить текущее значение `i` для каждой функции (несколько способов): 1) Использовать `let` (блочная область видимости — для каждой итерации своя `i`): ```js var funcs = []; for (let i = 0; i < 3; i++) { funcs.push(function(){ console.log(i); }); } funcs[0](); // 0 ``` 2) Замыкание через IIFE (функция немедленно вызывается и получает копию `i`): ```js var funcs = []; for (var i = 0; i < 3; i++) { (function(j){ funcs.push(function(){ console.log(j); }); })(i); } funcs[0](); // 0 ``` 3) Фабрика функций (передаём `i` как параметр и возвращаем функцию): ```js function makeLogger(j) { return function(){ console.log(j); }; } var funcs = []; for (var i = 0; i < 3; i++) { funcs.push(makeLogger(i)); } funcs[0](); // 0 ``` 4) Использовать `bind` для привязки аргумента: ```js var funcs = []; for (var i = 0; i < 3; i++) { funcs.push(console.log.bind(null, i)); } funcs[0](); // 0 ``` Итого: причина — одна общая `var`-переменная и замыкание на неё; решение — дать каждой итерации отдельную переменную/копию значения (через `let`, IIFE, фабрику или `bind`).
Как сохранить текущее значение `i` для каждой функции (несколько способов):
1) Использовать `let` (блочная область видимости — для каждой итерации своя `i`):
```js
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs.push(function(){ console.log(i); });
}
funcs[0](); // 0
```
2) Замыкание через IIFE (функция немедленно вызывается и получает копию `i`):
```js
var funcs = [];
for (var i = 0; i < 3; i++) {
(function(j){
funcs.push(function(){ console.log(j); });
})(i);
}
funcs[0](); // 0
```
3) Фабрика функций (передаём `i` как параметр и возвращаем функцию):
```js
function makeLogger(j) {
return function(){ console.log(j); };
}
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(makeLogger(i));
}
funcs[0](); // 0
```
4) Использовать `bind` для привязки аргумента:
```js
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(console.log.bind(null, i));
}
funcs[0](); // 0
```
Итого: причина — одна общая `var`-переменная и замыкание на неё; решение — дать каждой итерации отдельную переменную/копию значения (через `let`, IIFE, фабрику или `bind`).