@campus1

Почему такой результат?

Ребят изучаю JS, прошу пожалуйста поясните почему здесь выводится 10 раз 10??

for(var i=0; i<10; i++) {
  setTimeout(function() {
    alert(i);
  }, 100);
}


По сути цикла должно быть от 0 до 9.

Спасибо всем!
  • Вопрос задан
  • 1000 просмотров
Решения вопроса 4
0xD34F
@0xD34F Куратор тега JavaScript
Потому что все функции, переданные в setTimeout, вызываются после того, как цикл будет выполнен - а значение i к этому моменту будет равно 10.

Как исправить? Есть варианты:

for (var i = 0; i < 10; i++) {
  setTimeout(function() {
    alert(+this);
  }.bind(i), 100);
}

for (let i = 0; i < 10; i++) {
  setTimeout(function() {
    alert(i);
  }, 100);
}

for (var i = 0; i < 10; i++) {
  setTimeout(alert, 100, i);
}

for (var i = 0; i < 10; i++) {
  setTimeout(new Function(`alert(${i})`), 100);
}

for (var i = 0; i < 10; i++) {
  setTimeout(function() {
    alert(i++);
  }, 100);
}
i = 0;
Ответ написан
Комментировать
yarkov
@yarkov Куратор тега JavaScript
Помог ответ? Отметь решением.
for(let i=0; i<10; i++) {
  (function(i) {
      setTimeout(function() {
        alert(i);
  }, 100)})(i)
}

Но вы же знаете, что setTimeout не гарантирует порядок?
Ответ написан
twobomb
@twobomb
Ну всего скорее потому что setTimeout это асинхронный вызов функции через 100мс. В нем идет обращение к локальной переменной i, которая к этому моменту уже состовляет 10. Думаю этот цикл выполняется около 1мс, поэтому к моменту обращения к переменной i она уже равна 10. Чтобы выводило от 0 до 10 можно сделать так
for(var i=0; i<10; i++) {
  (function(i){setTimeout(function() {
    alert(i);
  }, 100);})(i);
}

но будет выводить не по порядку, так как это асинхронная функция. Короче говоря говоря цикл выполнится быстрее чем произойдет первый вызов функции.
P.S. Ну и напоследок можно попробовать приостанавливать цикл на каждой итерации и посмотреть что будет
(async function(){
for(var i=0; i<10; i++) {
  setTimeout(function() {
    alert(i);
  }, 100);
  await sleep(100);
}
})();
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
Ответ написан
Комментировать
teknik2008
@teknik2008
Расскажите про GOLANG. Мне интересно
Можно проще
for(let i=0; i<10; i++) {
  setTimeout(function() {
    alert(i);
  }, 100);
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы