Page 216 - Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017
P. 216

Теперь у нас  есть функция  без  побочных эффектов,  но это  все  еще не чистая
       функция, поскольку она не всегда возвращает один и тот же результат для одного
       и того же ввода. Для устранения этой проблемы следует тщательно рассмотреть, как
       мы используем данную функцию. Есть  шанс, что мы будем вызывать ее цикличе­
       ски, например в браузере, чтобы изменять цвет элемента два раза в секунду (о коде
       для браузера мы узнаем больше в главе 1 8 ).
       set Interval ( function ( )  {
           document . q uerySelector ( ' . rainbow ' )
               . s tyle [ ' background-color ' ]    =  getNextRainbowColor ( ) ;
       }  1  5 0 0 ) ;
          Выглядит не так уж и  плохо,  и,  конечно, намерение вполне однозначно: некий
       элемент HTML использует класс rainbow для циклической смены цвета. Проблема
                                                                 (
       в том, что если что-то еще вызовет метод getNextRainbowColor  ) , т о оно вмешается
       в работу этого кода! Здесь стоит остановиться и задаться вопросом "Настолько ли
       хорошей идеей является функция с побочными эффектами': В данном случае, веро­
       ятно, лучшим выбором был бы итератор.
       function  getRainbowiterator ( )    {
           const  colors  =  [ ' к расн ый  ' ,  ' о ранжевый ' ,    ' ж елтый ' ,    ' з елен ый  ' ,
                                          й
                           ' г олубой ' ,    ' с ини ' ,  ' ф иолетовый ' ] ;
           let  colorindex  =  - 1 ;
           return  {
               next  )    !
                   (
                   i f ( ++colorindex  >=  colors . l e ngth)  colorindex  = О ;
                   return  {  value :  colors [ colorindex ] ,   done :  false  } ;

           } ;


                                   w
          Наша функция  getRainbo i t e r a tor является теперь чистой:  она возвращает
       одно и то же каждый раз (итератор), и у нее нет никаких побочных эффектов. Мы
       могли бы использовать это иначе, но так намного безопаснее.
       const  rainbowi terator  =  getRainbowiterator ( ) ;
       setinterval ( function ( )    {
           document . q uerySelector ( ' . r i nbow ' )
                                    a
               . s tyle [ ' background-color ' ]    =  rainbowiterator . n ext ( )   . v a l ue ;
       } /  5 0 0 ) ;
          Вы могли бы подумать, что это только поверхностное решение проблемы: разве ме­
       тод next  )   не возвращает разные значения каждый разr Так и есть, однако вспомните,
               (
       что next ( ) является методом, а не функцией. Он работает в контексте объекта, которо­
       му принадлежит, поэтому его поведение контролируется этим объектом. Если мы будем
       использовать getRainbowlterator в других частях нашей программы, то они создадут
       разные итераторы, которые не будут конфликтовать ни с какими другими итераторами.


                                    Функции как подпрограммы, возвращающие значение   219
   211   212   213   214   215   216   217   218   219   220   221