Переосмысление JavaScript: Смерть for / Хабр
Цикл for
хорошо послужил нам, но он устарел и должен уступить место более новым, функциональным техникам программирования.
К счастью, этот факт не требует от вас быть мастером функционального программирования, более того, это то, что вы можете использовать в своих текущих проектах прямо сегодня!
Так в чем проблема цикла for в JavaScript?
Дизайн цикла for
подталкивает к мутациям состояния (англ. mutation of state — изменение состояния — прим. переводчика) и применению сайд эффектов (англ. side effects — побочные эффекты — прим. переводчика), которые являются потенциальными источниками багов и непредсказуемого поведения кода.
Все мы слышали, что глобальное состояние — это плохо, и что мы должны избегать его. Однако, локальное состояние разделяет те же проблемы что и глобальное, мы просто не сталкиваемся с ними так часто, ведь они проявляются в меньших масштабах.
Однажды, используя мутабельное состояние (англ. mutable state — изменяемое состояние — прим. переводчика), значение случайной переменной изменится по неизвестной причине, и вы потратите часы на отладку и поиск причины изменения. У меня волосы на голове встают дыбом, только от одной мысли об этом.
Я бы хотел немного поговорить о сайд эффектах. Эти слова даже звучат ужасно, сайд эффекты. Дрянь. Вы хотите чтобы в ваших программах были сайд эффекты? Нет, я не хочу сайд эффектов в моих программах!
Но что такое сайд эффекты?
Считается, что у функции есть сайд эффекты если она модифицирует что-то за пределами своей области видимости. Это может быть изменение переменной, пользовательский ввод, запрос к api, запись данных на диск, лог в консоль и т.д.
Сайд эффекты — действительно мощный инструмент, но с большой силой приходит большая ответственность.
Сайд эффекты, по возможности, должны быть устранены или хотя бы инкапсулированы так, чтобы мы могли их контролировать. Функции с сайд эффектами тяжелее читать и тестировать, избегайте их всегда, когда это возможно. К счастью, в рамках данной статьи, мы не будем беспокоиться о побочных эффектах.
Меньше слов, больше кода. Давайте посмотрим на типичный цикл for
, который вы вероятно видели сотни раз.
const cats = [ { name: 'Mojo', months: 84 }, { name: 'Mao-Mao', months: 34 }, { name: 'Waffles', months: 4 }, { name: 'Pickles', months: 6 } ] var kittens = [] // Типичный, плохо написанный цикл for for (var i = 0; i < cats.length; i++) { if (cats[i].months < 7) { kittens.push(cats[i].name) } } console.log(kittens)Я собираюсь отрефакторить этот код шаг за шагом, чтобы вы смогли пронаблюдать как легко превратить ваш собственный код в нечто более прекрасное.
Во-первых, я извлеку условное выражение в отдельную функцию:
const isKitten = cat => cat.months < 7 var kittens = [] for (var i = 0; i < cats.length; i++) { if (isKitten(cats[i])) { kittens. push(cats[i].name) } }Выносить условия — это в целом хорошая практика. Изменение фильтрации с “меньше чем 7 месяцев” на “является ли котенком” — большой шаг вперед. Теперь код передает наши намерения гораздо лучше. Почему мы берем котов до 7 месяцев? Не совсем понятно. Мы хотим найти котят, так пусть код говорит об этом!
Другая польза в том, что isKitten
теперь можно переиспользовать, а все мы знаем, переиспользование кода всегда должно быть нашей целью.
Следующее изменение — извлечь преобразование (или отображение) кота его в имя. Это изменение будет понятнее позднее, а сейчас просто доверьтесь мне.
const isKitten = cat => cat.months < 7 const getName = cat => cat.name var kittens = [] for (var i = 0; i < cats.length; i++) { if (isKitten(cats[i])) { kittens.push(getName(cats[i])) } }Я собирался написать несколько абзацев для описания механики работы
filter
и map
, но вместо этого, я покажу вам как легко читать и понимать этот код, даже увидев их (filter
и map
— прим. переводчика) впервые. Это лучшая демонстрация того, насколько читабельным может стать ваш код.const isKitten = cat => cat.months < 7 const getName = cat => cat.name const kittens = cats.filter(isKitten) .map(getName)Обратите внимание, мы избавились от
kittens.push(...)
. Никаких больше мутаций состояния и никаких var
Код отдающий предпочтение
const
перед var
и let
выглядит чертовски привлекательно
Конечно, мы могли использовать const
с самого начала, так как он не делает сам объект иммутабельным (об этом больше в другой раз), но это придуманный пример, не наседайте!И последнее изменение, я бы предложил также извлечь фильтрацию и отображение в функцию (для полного переиспользования кода).
И все вместе:
const isKitten = cat => cat.months < 7 const getName = cat => cat.name const getKittenNames = cats => cats.filter(isKitten) . map(getName) const cats = [ { name: 'Mojo', months: 84 }, { name: 'Mao-Mao', months: 34 }, { name: 'Waffles', months: 4 }, { name: 'Pickles', months: 6 } ] const kittens = getKittenNames(cats) console.log(kittens)
Домашнее задание
Изучить извлечение методов filter и map из их объектов. Задание со звездочкой: исследовать композицию функций.- Functional JavaScript: Decoupling methods from their objects
- Functional JavaScript: Function Composition For Every Day Use.
Что насчет break
Многие из вас спрашивали, “Что насчетbreak
”, посмотрите часть вторую серии “Переосмысление JavaScript: break это GOTO циклов”.- Rethinking JavaScript: Replace break by going functional
Заключение
Пишите что вы думаете по этому поводу в комментариях. Умер ли для вас циклfor
?Для вас это мелочь, но меня очень радует когда кто-то подписывается на меня на медиуме или в твиттере (@joelnet), а если вы считаете мой рассказ бесполезным, то расскажите об этом в комментариях.
Спасибо!
Цикл for…in и функции в JavaScript
Вы здесь: Главная >> Java-самоучитель >> Цикл for…in и функции в JavaScript
В языке JavaScript имеется также цикл for…in. Он позволяет работать со всеми элементами массива или со всеми свойствами объекта. О втором его предназначении (работа со свойствами объектов) мы поговорим в следующей главе, а вот о работе с массивами мы скажем сейчас. Этот цикл позволяет последовательно перебрать все элементы массива. В листинге 10.18 представлен пример работы с циклом for…in.
Листинг 10.18.
Работа с циклом for…in
Перейдем к работе с обособленными блоками кода — функциями. Это аналог методов в Java, которые здесь так не называются, так как не принадлежат классам. Рассмотрим работу с функциями на примере, представленном в листинге 10.19.
Листинг 10.19.
Работа с функциями
Мы создали три функции: первая — MyPrint — выводит на экран значение, переданное ей в параметре (аргументе), вторая — MyPrompt — получает строковое значение от пользователя и возвращает полученное значение.
При вызове третьей функции — MyFunc — вызываются первые две: вначале в переменную к записывается возвращаемое значение функции MyPrompt, а затем оно передается в качестве параметра функции MyPrint, которая выводит это значение на экран.
Чтобы функция не возвращала значение, можно применять при вызове оператор void, поставив его перед именем функции. Функции могут возвращать и сами себя — это называется рекурсией. О встроенных функциях мы поговорим в следующей главе.
Резюме
1. Весь текст HTML-страницы состоит из простого дескриптора и текстов. Дескрипторы располагаются между <> и позволяют произвести форматирование текста. Вместе они составляют текст HTML-страницы.
2. Текст, написанный на языке программирования JavaScript, встраивается в HTML- страницу с помощью так называемых сценариев.
3. По синтаксису JavaScript очень схож с Java. Он был разработан компанией Netscape и первоначально имел название LiveScript, однако за сходство с Java получил название JavaScript.
Вопросы
1. Что такое язык гипертекстовой разметки HTML?
2. Что такое язык программирования сценариев JavaScript?
3. Как их можно связать друг с другом?
Контрольные упражнения
1. Создайте несколько HTML-документов, связанных между собой, в которых будет рассказываться о новостях (страницы: Главная страница, Политика, Спорт, Погода).
3. Что неправильного в следующем HTML-документе (листинг 10.20).
2. Создайте HTML-документ со сценарием, где сценарий будет спрашивать пользователя его имя и выводить на экран приветствие.
Листинг 10.20.
Пример HTML-документа
Сергей Владимирцев
18.03.2011
Написание цикла for…in в JavaScript
В этом уроке мы покажем вам, как написать цикл for…in в JavaScript.
В JavaScript цикл for…in позволяет легко перебирать перечисляемые имена свойств объекта. Иногда эти имена также называют ключами свойств.
В отличие от цикла foreach в PHP, цикл for…in в JavaScript возвращает имена/ключи свойств объекта, а не их значения.
Этот тип цикла полезен, когда вы хотите быстро перебрать свойства объекта. Однако это не лучшее решение, если вы хотите перебирать массив.
Если вы хотите выполнить итерацию по массиву в JavaScript, вместо этого следует использовать цикл for…of, функцию « .forEach()
» или простой цикл for.
В следующих разделах мы покажем вам, как можно использовать цикл for…in.
Синтаксис цикла for…in в JavaScript
Давайте начнем это руководство с изучения того, как написать цикл for…in в JavaScript.
Вы запускаете цикл, используя ключевое слово « вместо
». В скобках вы сначала объявите переменную, которую будете использовать для хранения имени свойства в каждом цикле. Вы можете использовать « var
«, « let
» или « const
«, чтобы объявить эту переменную.
Затем используйте ключевое слово « в
», а затем имя объекта, который вы хотите повторить.
Для каждого цикла JavaScript будет перебирать указанный объект. Он присвоит имя свойства для этой итерации указанной переменной.
Использование цикла for…in в JavaScript
Мы рассмотрим различные примеры, чтобы показать вам, как цикл for…in работает в JavaScript.
Эти примеры также покажут вам некоторые из различных вариантов использования этого цикла. Тем не менее, его основное использование заключается в циклическом просмотре свойств объекта.
Перебор объекта с помощью цикла for…in в JavaScript
Начнем с одного из наиболее простых способов использования цикла for…in в JavaScript. Мы будем использовать цикл для перебора указанного объекта.
Мы начинаем код этого примера с создания объекта с именем « веб-сайт
» (объект определяется фигурными скобками {}
). Внутри этого объекта мы создаем три свойства с именами « url
», « name
» и « tutorial
».
Затем мы создаем наш JavaScript для… в цикле. Начнем с объявления переменной как const
с именем « key
». Затем мы используем ключевое слово « в
» и указываем « веб-сайт
» в качестве объекта, который мы хотим повторить.
В этом цикле мы используем функцию console.log()
для вывода имени свойства в каждом цикле. Используя этот ключ, вы также можете получить значение этого свойства.
После запуска этого JavaScript вы должны получить следующий результат. При этом вы можете увидеть, как цикл for…in повторяется над объектом, печатая каждое свойство.
Использование цикла for…in для перебора массива с помощью JavaScript
Вы можете использовать цикл for…in JavaScript для перебора ключей массива, поскольку они считаются объектами.
Однако, прежде чем приступить к этому примеру, мы должны отметить, что обычно не следует использовать цикл for..in для перебора массива. Вместо этого вы должны использовать цикл JavaScript for или цикл for…of.
Причина этого в том, что этот тип цикла выполняет итерацию по всем перечислимым элементам массива, и есть некоторые сложные правила, о которых вам нужно беспокоиться, чтобы гарантировать порядок массива.
В этом примере мы запускаем сценарий, объявляя массив с именем « пример
», в нем мы используем значения «Привет»
, «Мир»
, «PiMyLifeUp»
, «Учебник» 9001 4 .
Затем мы используем цикл for…in для перебора имен свойств нашего массива. В нашем случае это будет индекс массива.
У нас есть два случая использования функции console.log()
. Первый журнал печатает текущее значение ключа, а второй использует ключ для печати этого значения массива.
После выполнения этого примера кода JavaScript вы должны получить следующий результат.
Перебор строки с использованием цикла for…in
В этом примере мы будем использовать цикл for…in для перебора строки. Это возможно, поскольку строки по существу обрабатываются внутри как массив.
В верхней части скрипта мы создаем переменную с именем « example_string
» и присваиваем ей значение « Hello
».
Затем мы используем цикл for…in для перебора свойств переменной « example_string
». В каждом цикле мы печатаем имя текущего свойства (ключ), а затем букву в этой позиции в массиве.
Используя приведенный выше пример JavaScript, вы должны получить результат, аналогичный тому, что мы показали ниже.
Вывод
В этом руководстве мы показали, как писать и использовать цикл for..in в JavaScript.
Этот тип цикла позволяет быстро и эффективно перебирать свойства объекта. Однако обычно его не следует использовать для перебора массива.
Если у вас есть какие-либо вопросы о цикле for…in, оставьте комментарий ниже.
Обязательно ознакомьтесь с другими нашими руководствами по JavaScript или, если вы хотите выучить новый язык, с нашими многочисленными другими руководствами по программированию.
Все, что вам нужно знать о циклах в JavaScript
Циклы — это одна из первых вещей, которую вы изучаете как программист. Это не просто циклы for и while. У вас есть больше возможностей для зацикливания, чем вы, вероятно, захотите знать.
Давайте посмотрим.
FORКлассический. Старый Верный. Если вы уже знакомы, не стесняйтесь пропустить вперед.
Базовая структура цикла for проста. Повторяйте определенное количество кода, пока условие не будет выполнено. Для цикла for это условие должно выполняться определенное количество раз (если только сам код не предназначен для преждевременного выхода из цикла).
В цикл for передаются три оператора: начальная точка, конечная точка (условие выхода) и скорость, с которой цикл проходит от начальной до конечной точки.
"`
"`
Первый оператор
В 99% случаев начальная точка будет выглядеть как `i = 0`. Почему «я»? Просто этим все пользуются. Это как кодовый сленг. Не обязательно, но привычно. Предполагается, что оно означает «целое число», поскольку именно его вы увеличиваете.
Почему 0? Поскольку в JavaScript массивы имеют нулевой индекс, это означает, что первое значение в массиве находится в позиции 0, а не 1.
Второй оператор
Второй оператор `i < arr.length` означает, что цикл будет продолжаться. пока значение `i` не превысит длину `arr`, которая является массивом, который был объявлен перед циклом.
Оператор проверяется до , выполняется цикл. Если `i` больше, блок кода не запустится, и ваш цикл закроется.
Третье выражение
Третья часть, `i++`, является сокращением для `i += 1`, которое является сокращением для самого для `i = i + 1`. Все это означает, что вы повторяете `i` на 1. Таким образом, перед первым циклом `i` равно 0. Перед вторым циклом оно равно 1.
Третий оператор выполняет после блока кода. выполнил.
Соберите все вместе, и наш пример показывает, что цикл for будет повторяться 5 раз, прежде чем двигаться дальше.
“`
"`
Вы можете использовать базовый цикл for, чтобы зациклить определенное количество раз или зациклить массив, строку или подобный массиву объект (используя свойство `.length` того, что вы хотите пытаюсь зациклиться). Это самая универсальная конфигурация и наиболее часто реализуемая.
FOR…INПроще говоря, эта форма цикла позволяет вам проходить через объект.
Чтобы быть более точным, я позаимствую определение из веб-документов Mozilla: «Операция for…in выполняет итерацию по всем перечислимым свойствам объекта, которые задаются строками (игнорируя те, которые задаются символами)».
Давайте рассмотрим пример.
"`
"`
Примечание : значение, которое вы называете перед использованием ключевого слова `in`, относится к каждому ключу . Для доступа к значению нужно вызвать объект по ключу (как в примере выше).
FOR…OFЭтот синтаксис выглядит так же, как `for…in`, за исключением того, что он работает для массивов и строк.
"`
"`
Довольно просто.
Примечание: Метод forEach() работает точно так же, за исключением только массивов. Если вы зацикливаете массив, используйте его вместо этого (это проще).
WHILEЦикл while повторно выполняет блок кода снова и снова, пока не будут выполнены критерии выхода. Это похоже на цикл for, за исключением только третьего оператора.
Допустим, вы пытаетесь создать программу для игры в блэкджек. Пока у вас есть деньги выше нуля, вы хотите запустить функцию `playHand()`.
Функция `playHand()` добавит или удалит ваши общие деньги в зависимости от того, насколько удачна рука. Если все идет хорошо, вы хотите, чтобы программа продолжала играть.
"`
"`
Примеры циклов while сложны, потому что практических вариантов их использования немного. Это одна из первых петель, которую вы изучаете, и все же я видел ее «в дикой природе» , может быть, раз. Почти всегда предпочтительнее использовать цикл for.
Даже в примере с блэкджеком предполагается, что вы можете играть в игру мгновенно, или функция `playHand` имеет встроенные ожидания — в противном случае код будет выполняться снова мгновенно и бесконечно. Цикл while является самым опасным из всех методов зацикливания javascript, потому что он потенциально может зацикливаться вечно (что, как вы знаете, плохо).
Использование цикла while влечет за собой некоторую случайность, что обычно не то, что вы хотите создать как разработчик.
DO…WHILEАналогично циклу while, за исключением того, что вы гарантируете, что функция будет выполнена хотя бы один раз. Вместо проверки критериев выхода перед выполняется вход в цикл, как в обычном цикле while, он проверяется в конце.
"`
"`
FOREACH()Метод forEach() применяется к массивам. Он перебирает массив, как и ожидалось, и выполняет блок кода на каждой итерации.
"`
"`
В этом примере показан цикл через `arr`, где каждое значение записывается в консоль. Простой.
С вычислительной точки зрения это не имеет никакого реального преимущества по сравнению с созданием обычного цикла for с `arr`, как в нашем самом первом примере вверху страницы, но он выглядит намного чище!
Наряду с приведенной ниже функцией map() и базовым циклом for, forEach() представляет собой циклический подход, который я чаще всего встречаю в дикой природе.
MAP()Другой метод, `map()` (не путать с объектом `Map`), выглядит и работает очень похоже на `forEach()` , кроме , вы фактически создаете совершенно новый массив.
Новый массив создается с результатами любого кода, выполняемого в каждом цикле.
"`
"`
БОНУС: FILTER()Хотя его можно использовать для перебора массива, `filter()` находится в серой зоне. Здесь вы не зацикливаетесь, чтобы что-то сделать с каждым из значений, и вы не выполняете действие в зависимости от того, сколько раз вы выполняете цикл.
Вместо этого `filter()` возвращает подмножество передаваемого вами массива на основе критериев. Отсюда и название «фильтр».
Например, у нас есть массив `[1, 2, 3, 4, 5]`, и нам нужны только четные значения. Мы можем создать новый массив только с четными значениями, используя такой фильтр:
"`
"`
Вы применяете метод `filter()` к массиву и передаете функцию, которая возвращает логическое значение. Когда каждое значение в массиве проходит через функцию и возвращает true, это исходное значение возвращается как часть нового массива.
Это сделало бы `newArr` новым массивом со значениями `[2,4]`.
Вы также можете абстрагировать функцию и передать ее имя методу фильтра:
"`
"`
И newArr будет таким же, как исходная, абстрагированная стрелочная функция.
ПОСЛЕДНЕЕ СЛОВОКонечно, есть много других хитростей, которые вы можете использовать для итерации, манипулирования и поиска в массивах (например, `reduce()`, `values()`, `Object.