Почему в одном случае функция не сохраняет переменную, а в другом сохраняет

function makeArmy() {
  let shooters = [];

  let i = 0;
  while (i < 10) {
    let shooter = function() { // функция shooter
      alert( i ); // должна выводить порядковый номер
    };
    shooters.push(shooter);
    i++;
  }

  return shooters;
}

let army = makeArmy();

army[0](); // у 0-го стрелка будет номер 10
army[5](); // и у 5-го стрелка тоже будет номер 10
// ... у всех стрелков будет номер 10, вместо 0, 1, 2, 3.
function makeArmy() {
  let shooters = [];

  let i = 0;
  while (i < 10) {
    let j = i;
    let shooter = function() { // функция shooter
      alert( j ); // должна выводить порядковый номер
    };
    shooters.push(shooter);
    i++;
  }

  return shooters;
}

let army = makeArmy();

army[0](); // 0
army[5](); // 5

Почему в первом случае переменная i не сохраняется, а во втором просто присваивая она сохраняется. Т.е while создаёт каждой функции свое другое лексическое окружение?


Ответы (1 шт):

Автор решения: ΝNL993

Всё легко, в первым случае, вы дальше увеличиваете i, которая в итоге становиться 10-кой. А shooter до сих пор выводит i, а не текущее число. Можно увидеть это в подобном примере:

Во втором случае же, вы сохраняете текущее число в переменную, теперь получается что shooter, выводит так нужное число (то, которые вы сохранили в j).

Можно от этого избавиться использовав обычный for цикл:

function makeArmy() {
  let shooters = [];

  for (let i = 0; i < 10; i++) {
    let shooter = function() { // функция shooter
      alert( i ); // должна выводить порядковый номер
    };
    shooters.push(shooter);
  }

  return shooters;
}

let army = makeArmy();

army[0](); // 0
army[5](); // 5

→ Ссылка