splincodewd
@splincodewd
Developer

Как понять такое поведение участка кода на js?

Мда, после такого считаю себя нубом.

1) Что выведется в консоль? Как добиться правильного вывода в консоль, не убирая setTimeout?
for (var i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log(i); // ?
  }, 0);
}


Думал, что раз у setTimeout нет задержки, он будет сразу выполнять код внутри себя, оказывает нет
Вставлял такой код несколько раз в консоль, в итоге вывод:

58eb04456b544936925189c9509e0f2d.png

Как объясняется такое поведение?
  • Вопрос задан
  • 448 просмотров
Решения вопроса 5
impeee
@impeee
nodejs/erlang developer
for (var i = 0; i < 10; i++) {
  setTimeout((function (i) {
    console.log(i); // ?
  })(i), 0);
Ответ написан
@void01
цикл пробегается раньше чем отрабатывает timeout
/* написаное ниже - ошибочно */
JS однопоточен, поэтому setTimeout фактически выбрасывает код в конец текущего обработчика, когда i == 10
/* написаное выше - ошибочно */

можно прибегнуть к ES6 и использовать оператор let
for (let i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log(i); // ?
  }, 0);
}


таким образом мы сократили область видимости переменной i до блока внутри цикла
а в случае с var переменная была общая и setTimeout выводил только ее конечное значение

UPD: дока для ознакомления тут https://learn.javascript.ru/let-const

UPD2: По поводу однопоточности я ошибся (в том что это причина).
Исправляюсь )) как оказалось. setTimeout(func,0) и setTimeout(func,4) выполнятся одновременно.
По крайней мере в хроме. минимальный порог значения таймаута в разных браузерах может отличаться, но он больше 0мс. В хром это 4мс. обусловлено это тем, что многие используют setTimeout для асинхронности и страница где несколько setTimeout(func,0) сильно нагрузит процессор. По крайней мере базовой причиной появляения минимальной задержки называют это.
Ответ написан
Finesse
@Finesse
Чтобы добиться правильного вывода, нужно создать замыкание. Например, так:
for (var i = 0; i < 10; i++) {
  // Значение переменной i копируется в переменную value, которая при каждом из 10 вызовов отдельная
  (function(value) {
    setTimeout(function () {
      console.log(value);
    }, 0);
  })(i);
}
Ответ написан
Комментировать
DirecTwiX
@DirecTwiX
"display: flex;" уже предлагали?
https://learn.javascript.ru/settimeout-setinterval
or (let i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log(i); // ?
  }, 0);
}
Ответ написан
Комментировать
@G_tost
Fullstack developer
setTimeout(func,time) - добавит указанную функцию через time милисекунд в очередь выполнения функций.
Т.е фукнция выполнится через time мс только в том случае если в очереди нету никаких задач , типа рендеринга страниц и тд .
+
вот такой блок кода будет в цикле добавлять с очередь выполения функци которым передали значение индекса цикла.
```
for (var i = 0; i < 10; i++) {
setTimeout(function (index) {
console.log(index);
} ,0,i);
```
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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