Page 219 - Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017
P. 219
Обратите внимание, что здесь мы используем var вместо l e t . Давайте рассмот
рим, почему IIFE так важны. Если вы ожидаете увидеть вывод 5, 4 , 3, 2, 1 , "Старт ! " ,
-
то будете разочарованы. Вместо этого вы найдете шесть раз выведенное число 1 .
Дело в том, что функция, передаваемая setTimeout, вызывается не сразу в цикле,
а через некоторое время. Таким образом, цикл выполнится начиная с i, равного 5,
и в конечном счете достигнет -1 ... еще до того, как любая из функций будет вызвана.
-
Таким образом, на момент вызова функции i будет иметь значение 1 .
п
(
Даже при том, что область видимости уровня блока с переменными let), о су
ществу, решает эту проблему, данный пример все еще очень важен, если вы новичок
в асинхронном программировании. Трудно объять необъятное, но понимание асин
хронного выполнения критически важно (глава 14).
Без применения переменных области видимости уровня блока для решения этой
задачи нужно было использовать другую функцию. При использовании дополни
тельной функции создается новая область видимости, и значение i может быть "за
фиксировано" (в замкнутом выражении) на каждом этапе. Рассмотрим сначала ис
пользование именованной функции.
function loopBody ( i) {
setTimeout ( f unction ( )
console . l og ( i ===O ? " С тарт ! " i ) ;
} ' ( 5 - i ) * 1 0 0 0 ) ;
var i ;
for ( i =S ; i > O ; i--)
loopBody ( i ) ;
На каждом этапе цикла вызывается функция loopBody. Напомню, что в JavaScript
аргументы передаются функции при вызове по значению. Таким образом, на каж
дом этапе функции передается не переменная i, а ее значение. Вначале передается
значение 5, во второй раз - значение 4 и т.д. Не имеет значения, что в обоих местах
мы используем имя переменной (i): по существу, мы создаем шесть разных областей
видимости и шесть независимых переменных (одну для внешней области видимости
и пять для каждого из вызовов loopBody).
Но все же создание именованной функции для цикла, который вы собираетесь
использовать только однажды, довольно утомительное занятие. Задействуйте IIFE:
они, по существу, создают эквивалентные анонимные функции, которые вызываются
немедленно. Вот как предыдущий пример выглядит с IIFE.
var i ;
for ( i =S ; i > O ; i-- ) {
( function ( i ) {
setTimeout ( f unction ( )
console . l og ( i===O ? "Старт ! " i ) ;
222 Глава 1 3 . Функции и мощь абстрактного мышления

