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 . Функции и мощь абстрактного мышления
   214   215   216   217   218   219   220   221   222   223   224