0
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 создаёт каждой функции свое другое лексическое окружение?

Grundy
  • 81,538
hodini
  • 1
  • Это полный дубликат. Не важно как вызывается функция. Главное что она вызывается не сразу в момент объявления. – Grundy Jan 12 '23 at 17:15

1 Answers1

-2

Всё легко, в первым случае, вы дальше увеличиваете 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();

army0; // 0 army5; // 5

ΝNL993
  • 3,453
  • Т.е while в каждом цикле отдельно свои переменные в отдельных лексических видимостях хранит? Например, во втором случае, когда вводится army0 вызывается функция, которая возвращает j, но откуда она знает, что это именно та j? Т.е каждый цикл создаёт свою среду? – hodini Jan 12 '23 at 09:57
  • Т.е получается в первом случае т.к переменная объявлена выше, она никак не будет относится к этой локальной области? Т.е там i это ссылка на переменную, которая стала уже в конце цикла 10, поэтому все функции ссылаются на одну и ту же переменную которая не в их локальной области видимости? – hodini Jan 12 '23 at 10:05
  • @hodini если я вас правильно понял, то да. i в первом случае объявлена для функций которые ниже "глобально", а они сами просто ссылаются на неё, что и приводит вас, к вашей проблеме. – ΝNL993 Jan 12 '23 at 10:07