for
, который выглядит примерно так: for (var i=0; i < value.length; i++ ){}
. Однако, лучше, всё-таки, смотреть на вещи шире.![image](https://habrastorage.org/getpro/habr/post_images/1fe/db9/281/1fedb9281ec46d21e3bfbd075eb765eb.png)
Предположим, нам надо вывести список товаров, и, при необходимости, разбивать его на категории, фильтровать, выполнять по нему поиск, модифицировать этот список или его элементы. Возможно, требуется быстро выполнить некие вычисления, в которые будут вовлечены элементы списка. Скажем, надо что-то с чем-то сложить, что-то на что-то умножить. Можно ли найти в JavaScript такие средства, которые позволяют решать подобные задачи быстрее и удобнее, чем с использованием обычного цикла
for
?На самом деле, такие средства в JavaScript имеются. Некоторые из них рассмотрены в материале, перевод которого мы представляем сегодня вашему вниманию. В частности, речь идёт об операторе расширения, о цикле
for…of
, и о методах includes()
, some()
, every()
, filter()
, map()
и reduce()
. Здесь мы, в основном, будем говорить о массивах, но рассматриваемые здесь методики обычно подходят и для работы с объектами других типов.Надо отметить, что обзоры современных подходов к разработке на JS обычно включают в себя примеры, подготовленные с использованием стрелочных функций. Возможно, вы не особенно часто пользуетесь ими — может быть из-за того, что вам они не нравятся, может быть потому, что не хотите тратить слишком много времени на изучение чего-то нового, а, возможно, они просто вам не подходят. Поэтому здесь, в большинстве ситуаций, будут показаны два варианта выполнения одних и тех же действий: с использованием обычных функций (ES5) и с применением стрелочных функций (ES6). Для тех, у кого нет опыта работа со стрелочными функциями, отметим, что стрелочные функции не являются эквивалентами объявлений функций и функциональных выражений. Не стоит механически заменять одно на другое. В частности, это связано с тем, что в обычных и стрелочных функциях ключевое слово
this
ведёт себя по-разному.1. Оператор расширения
Оператор расширения (spread operator) позволяет «раскрывать» массивы, подставляя в то место, где использован этот оператор, вместо массивов, их элементы. Похожий подход предложен и для литералов объектов.
?Сильные стороны оператора расширения
- Это — простой и быстрый способ «вытащить» из массива его отдельные элементы.
- Этот оператор подходит для работы с литералами массивов и объектов.
- Это — быстрый и интуитивно понятный метод работы с аргументами функций.
- Оператор расширения не занимает много места в коде — он выглядит как три точки (…).
?Пример
Предположим, перед вами стоит задача вывести список ваших любимых угощений, не используя при этом цикл. С помощью оператора расширения это делается так:
![](https://habrastorage.org/getpro/habr/post_images/294/507/e34/294507e346cfbb4f379f724f4b69f3d8.png)
2. Цикл for…of
Оператор
for…of
предназначен для обхода итерируемых объектов. Он даёт доступ к отдельным элементам таких объектов (в частности — к элементам массивов), что, например, позволяет их модифицировать. Его можно считать заменой обычному циклу for
.?Сильные стороны цикла for…of
- Это — простой способ для добавления или обновления элементов коллекций.
- Цикл
for…of
позволяет выполнять различные вычисления с использованием элементов (суммирование, умножение, и так далее). - Им удобно пользоваться при необходимости выполнения проверки каких-либо условий.
- Его использование ведёт к написанию более чистого и читабельного кода.
?Пример
Предположим, у вас имеется структура данных, описывающая содержимое ящика с инструментами и вам надо показать эти инструменты. Вот как это сделать с помощью цикла
for...of
:![](https://habrastorage.org/getpro/habr/post_images/fcb/9c9/658/fcb9c9658df9e359579d30abc8690ddc.png)
3. Метод includes()
Метод
includes()
используется для проверки наличия в коллекции некоего элемента, в частности, например, определённой строки в массиве, содержащем строки. Этот метод возвращает true
или false
в зависимости от результатов проверки. Пользуясь им, стоит учитывать, что он чувствителен к регистру символов. Если, например, в коллекции есть строковой элемент SCHOOL
, а проверка на его наличие с помощью includes()
выполняется по строке school
, метод вернёт false
.?Сильные стороны метода includes()
- Метод
includes()
полезен в деле создания простых механизмов поиска данных. - Он даёт разработчику интуитивно понятный способ определения наличия неких данных в массиве.
- Его удобно использовать в условных выражениях для модификации, фильтрации элементов, и для выполнения других операций.
- Его применение ведёт к улучшению читабельности кода.
?Пример
Предположим, у вас имеется гараж, представленный массивом со списком автомобилей, и вы не знаете, есть в этом гараже некий автомобиль, или нет. Для того чтобы решить эту проблему, надо написать код, который позволяет проверять наличие автомобиля в гараже. Воспользуемся методом
includes()
:![](https://habrastorage.org/getpro/habr/post_images/286/620/764/28662076415c534ab2b6d1b049594341.png)
4. Метод some()
Метод
some()
позволяет проверить, существуют ли некоторые из искомых элементов в массиве. Он, по результатам проверки, возвращает true
или false
. Он похож на вышерассмотренный метод includes()
, за исключением того, что его аргументом является функция, а не, например, обычная строка.?Сильные стороны метода some()
- Метод
some()
позволяет проверить, имеется ли в массиве хотя бы один из интересующих нас элементов. - Он выполняет проверку условия с использованием переданной ему функции.
- Он способствует применению декларативного подхода при программировании.
- Этим методом удобно пользоваться.
?Пример
Предположим, вы — владелец клуба, и в общем-то, вас не интересует — кто именно в ваш клуб приходит. Однако, некоторым посетителям вход в клуб закрыт, так как они склонны к излишнему потреблению спиртных напитков, по крайней мере, в том случае, если они оказываются в вашем заведении сами, и с ними нет никого, кто может за ними присмотреть. В данном случае группе посетителей можно войти в клуб только при условии, что хотя бы одному из них не меньше 18-ти лет. Для того чтобы автоматизировать проверку подобного рода, воспользуемся методом
some()
. Ниже его применение продемонстрировано в двух вариантах.ES5
![](https://habrastorage.org/getpro/habr/post_images/f14/57d/ba1/f1457dba18588a5d88239a1b16de8c5d.png)
ES6
![](https://habrastorage.org/getpro/habr/post_images/61e/d46/3ff/61ed463ff9ac575d9bcd28328cb2a97e.png)
5. Метод every()
Метод
every()
обходит массив и проверяет каждый его элемент на соответствие некоему условию, возвращая true
в том случае, если все элементы массива соответствуют условию, и false
в противном случае. Можно заметить, что он похож на метод some()
.?Сильные стороны метода every()
- Метод
every()
позволяет проверить соответствие условию всех элементов массива. - Условия можно задавать с использованием функций.
- Он способствует применению декларативного подхода при программировании.
?Пример
Вернёмся к предыдущему примеру. Там вы пропускали в клуб посетителей, не достигших 18 лет, но кто-то написал заявление в полицию, после чего вы попали в неприятную ситуацию. После того, как всё удалось уладить, вы решили, что вам всё это ни к чему и ужесточили правила посещения клуба. Теперь группа посетителей может пройти в клуб только в том случае, если возраст каждого члена группы не меньше 18 лет. Как и в прошлый раз, рассмотрим решение задачи в двух вариантах, но на этот раз будем пользоваться методом
every()
.ES5
![](https://habrastorage.org/getpro/habr/post_images/c2a/fee/ebd/c2afeeebd3e61babe3c6c5f1f6e34f51.png)
ES6
![](https://habrastorage.org/getpro/habr/post_images/c6d/abb/e6d/c6dabbe6dd74dfae9e8f69e0c2e5398b.png)
6. Метод filter()
Метод
filter()
позволяет создать, на основе некоего массива, новый массив, содержащий только те элементы исходного массива, которые удовлетворяют заданному условию.?Сильные стороны метода filter()
- Метод
filter()
позволяет избежать модификации исходного массива. - Он позволяет избавиться от ненужных элементов.
- Он улучшает читабельность кода.
?Пример
Предположим, вам надо отобрать из списка цен только те, которые больше или равны 30. Воспользуемся для решения этой задачи методом
filter()
.ES5
![](https://habrastorage.org/getpro/habr/post_images/516/085/b44/516085b445b8b19e6be23694106c7ff2.png)
ES6
![](https://habrastorage.org/getpro/habr/post_images/08f/47a/289/08f47a28948391023ac2b8a3cbe2b82c.png)
7. Метод map()
Метод
map()
похож на метод filter()
тем, что он тоже возвращает новый массив. Однако он применяется для модификации элементов исходного массива.?Сильные стороны метода map()
- Метод
map()
позволяет избежать необходимости изменения элементов исходного массива. - С его помощью удобно модифицировать элементы массивов.
- Он улучшает читаемость кода.
?Пример
Предположим, у вас имеется список товаров с ценами. Вашему менеджеру нужен новый список товаров, цены которых снижены на 25%. Воспользуемся для решения этой задачи методом
map()
.ES5
![](https://habrastorage.org/getpro/habr/post_images/6da/c34/58a/6dac3458af0e37653a165e7efb7528a7.png)
ES6
![](https://habrastorage.org/getpro/habr/post_images/bfc/fee/85c/bfcfee85c35aea49271041d1fe6c450e.png)
8. Метод reduce()
Метод
reduce()
, в его простейшем виде, позволяет суммировать элементы числовых массивов. Другими словами, он сводит массив к единственному значению. Это позволяет использовать его для выполнения различных вычислений.?Сильные стороны метода reduce()
- С помощью метода
reduce()
можно посчитать сумму или среднее значение элементов массива. - Этот метод ускоряет и упрощает проведение вычислений.
?Пример
Предположим, вам надо посчитать ваши расходы за неделю, которые хранятся в массиве. Решим эту задачу с помощью метода
reduce()
.ES5
![](https://habrastorage.org/getpro/habr/post_images/e34/d3d/6ef/e34d3d6efbc56cafce03ceb18a50e38b.png)
ES6
![](https://habrastorage.org/getpro/habr/post_images/a17/e26/160/a17e261605fb96a60a34f740305792ee.png)
Итоги
В этом материале мы рассмотрели некоторые полезные приёмы, которые упрощают и ускоряют работу с массивами и улучшают читаемость кода. Если сегодня состоялось ваше первое знакомство с этими приёмами, рекомендуем, пользуясь полученной здесь базой, узнать о них побольше и поэкспериментировать с ними самостоятельно. Уверены, всё это вам пригодится.
Уважаемые читатели! Знаете ли вы какие-нибудь интересные, но не слишком широко известные методы работы с массивами в JavaScript?
![](https://habrastorage.org/files/1ba/550/d25/1ba550d25e8846ce8805de564da6aa63.png)
Комментарии (23)
Splo1ter
11.05.2018 12:58+1Хм… ничего нового, все это можно в интернете найти на английском языке и без промо в футере.
И это в блоге компании занимающейся VDS/VPS…Juma
11.05.2018 14:50все это можно в интернете найти на английском языке
И искать не надо, здесь все есть, на русском, подробно и с более удачными примерами, так же указана совместимоть методов с версиями браузеров.
И это в блоге компании занимающейся VDS/VPS…
Видимо имеют в виду: Покупайте сервер, и разворачивайте сайт на node.js
k12th
11.05.2018 13:24Метод reduce(), в его простейшем виде, позволяет суммировать элементы числовых массивов. Другими словами, он сводит массив к единственному значению.
В простейшем виде он именно что сводит массив к единственному значению, про суммирование — в лучшем случае распространенный пример.
Кстати, это "единственное значение" вполне может быть другим массивом, что позволяет делать filter + map за один проход без мудреных концепций типа Y-комбинаторов и т.п.
Juma
11.05.2018 15:06Понимаю, что перевод но все же примеры кода не удачные. Например, что делает вот эта строчка (и другие похожие):
age.some(person => person >= 18);
Понятно, что консоль выведет результат вычисления (просто консоль так задумана).
Но это ведь не явно. Глядя на код — это мертвая строчка, которая просто будет жрать ресурсы. А как именно использовать этот метод не ясно.
Пара вариантовconst age = [16, 17, 18]; const adultPresent = age.some(person => person >= 18); console.log(adultPresent);
или
const age = [16, 17, 18]; const adultPresent = age.some(person => { if (person >= 18) { console.log(true); return true; } });
impwx
11.05.2018 18:58Не соглашусь. При наличии описания, примера вызова и результата работы вызов
console.log(...)
не делает код ничуть понятнее, а только захламляет его.
shmatuan
11.05.2018 16:28Первый пример не показывает весь смысл такого использования — проще же .join() использовать для обычного массива
ИМХО нужно было показать в таком стиле:
let a = [{a: 1}, {b: 2}] console.log(...a) // -> {a: 1} {b: 2} console.log(a.join(' ')) // -> [object Object] [object Object]
rockon404
11.05.2018 18:08+5Статья называется «Полезные приёмы работы с массивами», в самой статье описаны стандартные методы в базовых примерах, да и то не все, пара операторов и ни одного «полезного приема».
Если авторы оригинала хотели удивить читателей удобным синтаксисом и возможностями ES6, то они года на три опоздали.
donatello2005
12.05.2018 10:23Прошу прощения, что придираюсь (да и это перевод, не здесь надо делать замечания), но хотелось бы хотя бы в комментарии добавить про forEach (а то про for..of написано, про map написано, а про forEach — нет). Плюс стоит упомянуть про reduceRight (хотя бы через слэш после reduce). И в одном из примеров по моему мнению не хватает второго необязательного аргумента для reduce, который задаёт начальное состояние результирующей переменной (часто использую).
Brodyagos
12.05.2018 10:23А на сколько map быстрее перебора foreach? У меня нарисовалась задача по перебору массива и добавлению новый в ~300 000 элементов на клиенте и с использованием невыносимо долго около 2 — 3 минут…
donatello2005
12.05.2018 14:15+1Если хотите ускорить процесс — используйте
for(let i = 0; i < yourArray.length; i++) {}
Это — самый быстрый вариант цикла:
jsperf.com/fast-array-foreach
С тех пор (тест 2012-го года, но можно найти и тесты недельной давности — результат будет схожим) хоть и обещали оптимизировать forEach/map в V8-движке, но до сих пор весомых результатов так и не добились.
forEach/map — это удобно, но при их использовании приходится жертвовать производительностью. Сейчас с нынешними возможностями ПК и мобильных устройств это зачастую не критично, но на больших объёмах данных, где падение скорости выполнения цикла в 6 раз — критичный момент (вместо, например, 2-х секунд выполнения процесс обработки займёт 12), стоит пренебречь удобством в пользу скорости выполнения. То же касается и остальных функций, представленных в статье выше.Brodyagos
12.05.2018 14:51Спасибо, попробую на for перевести цикл… Вообще удивительно конечно. У нас в проекте встречаются таблицы для заполнения размером 20 х 50, 200 х 200, разок было 2000 х 20, работало относительно нормально (крайний случай проглатывался на слабых компьютерах за одну минуту). Новая форма 250 х 2000 и у отдельных пользователей все встаёт раком (по другому и не сказать) до 20 минут с многократными предупреждениями о долгом исполнении в результате данные "бьются".
По уму это будет прекрасно работать на vue когда новый набор (строка) будет писаться в виде нового массива данных во внутрь большего набора по факту новой строки, а большой массив уже прекрасно пройдёт сериализацию для отправки на сервер
holder
12.05.2018 15:18Всем этим очень аккуратно нужно пользоваться, если подразумевается хоть какая-то поддержка IE. Надо бы хотя бы вскользь упомянуть, что как минимум includes() и of() в нем не поддерживается.
JokerNN
Понимаю, что перевод, но всё-таки переменную в
for...of
лучше сделать локальной.Вот так: