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

