ES-6 вспомогательные функции для работы с массивами
Итак, ES-6 подарил нам целых 7 новых функций для работы с массивами:
- Функция
forEach
- Функция
map
- Функция
filter
- Функция
reduce
- Функция
find
- Функция
every
- Функция
some
Пойдём по порядку.
Функция forEach
Функцию forEach
можно рассматривать как альтернативу привычному циклу for
. Всё, что она делает — это перебирает каждый элемент массива и вызывает для него функцию-итератор.
Синтаксис
array.forEach(function(currentValue, index, arr), thisValue)
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
Посмотрим на примере, как это работает. Допустим, у нас есть массив с рецептами, в котором у каждого рецепта есть название и список ингредиентов.
const recipes = [ { title: "Омлет", ingredients: [ "яйца", "сливки", "сливочное масло", "соль" ] }, { title: "Картофельное пюре", ingredients: [ "картофель", "сливочное масло", "молоко", "соль" ] }]// ИСПОЛЬЗУЕМ ТРАДИЦИОННЫЙ FOR ЦИКЛfor (let i = 0; i < recipes.length; i++) { console.log(recipes[i].title); // Омлет, Картофельное пюре}// ТО ЖЕ САМОЕ С forEachrecipes.forEach((item) => { console.log(item.title); // Омлет, Картофельное пюре})
Очевидно, что запись forEach
короче и легче для чтения. Это, возможно, не так очевидно на примере выше. Но давайте возьмём более приближенный к реальности случай и выведем список ингредиентов для каждого рецепта. С for
циклом это будет выглядеть так:
for (let i = 0; i < recipes.length; i++) { let recipe = recipes[i]; for (let j = 0; j < recipe.ingredients.length; j++) { let ingredient = recipe.ingredients[j]; console.log(ingredient) }}
Довольно громоздкий код, две временные переменные i
и j
. Легко запутаться и допустить ошибку. А вот как тот же результат получить с помощью forEach
:
recipes.forEach((recipe) => { recipe.ingredients.forEach((ingredient) => { console.log(ingredient); })})
Согласитесь, здесь преимущество forEach
уже более очевидно. В общем смело можете вместо for
циклов использовать forEach
. Единственный случай, когда for
цикл не удастся заменить — это если вам нужно при достижении какого-то условия прекратить выполнение цикла и выйти из него. В случае с for
циклом можно использовать break
. При использовании forEach
такой возможности нет.
Функция map
Функция map
создаёт новый массив из элементов исходного массива, принимая в качестве аргумента функцию и выполняя её для каждого элемента. И всё это без влияния на первоначальный массив.
Синтаксис
array.map(function(currentValue, index, arr), thisValue)
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
Ну и естественно для большей наглядности рассмотрим пару примеров. Пусть у нас есть массив номеров и нам нужно получить новый массив с удвоенными значениями номеров.
const numbers = [1, 2, 3, 4, 5, 6];//БЕЗ MAPconst doubledNumbers = [];for (let i = 0; i < numbers.length; i++) { doubeldBumbers.push(numbers[i] * 2);}// С MAPconst mapDoubledNumber = numbers.map((number) => number * 2);
Как видите, функция map
также отличается лаконичностью. Но главное, она всегда возвращает новый массив такого же размера, как исходный.
Функция filter
Суть данной функции легко определить по названию. Она позволяет отфильтровать элементы массива. Возвращает новый массив, состоящий из элементов исходного массива, отвечающих заданным критериям.
Синтаксис
array.filter(function(currentValue, index, arr), thisValue)
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
Ну и как обычно, пример. Допустим нам нужно из массива c рецептами получить только вегетарианские рецепты. Вы уже догадались, что сейчас я работаю над приложением с рецептами? Да, так что примеры из реальной жизни. )
const recipes = [ { title: "Омлет", ingredients: [ "яйца", "сливки", "сливочное масло", "соль" ], isVegeterian: true }, { title: "Картофельное пюре", ingredients: [ "картофель", "сливочное масло", "молоко", "соль" ], isVegeterian: true }, { title: "Котлеты", ingredients: [ "говяжий фарш", "сухари панировочные", "яйца", "лук" ], isVegeterian: false }]// БЕЗ FILTERconst vegRecipes = [];for (let i = 0; i < recipes.length; i++) { if (recipes[i].isVegeterian) { vegRecipes.push(recipes[i]); }}// C FILTERconst filteredRecipes = recipes.filter((recipe) => recipe.isVegeterian);
Вот так красиво, элегантно, в одну строку. И без изменения исходного массива.
Функция reduce
Эта функция обычно вызывает самые большие затруднения. Многим она кажется сложной, но это не так. Её суть в том, что она позволяет уменьшить массив, свести его к одному значению. Для каждого элемента исходного массива вызывается указанная функция в которую передаются текущий элемент массива и переменная-аккумулятор, в которой мы сохраняем результат выполнения функции, и которая в итоге возвращается как финальный результат.
Синтаксис
array.reduce(function(acc, currentValue, index, arr), initialValue)
Принимаемые аргументы
- acc – Обязательный аргумент. Переменная-аккумулятор. initialValue при первой итерации и результат выполнения предыдущих итераций при последующих вызовах;
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- initialValue – Опциональный аргумент. Начальное значение переменной-аккумулятора. Если не передавать, то по умолчанию используется 0
Ну и пример поможет нам лучше понять это всё. Допустим, у нас есть массив с числами и нам нужно получить сумму всех этих чисел.
const numbers = [10, 20, 30, 40, 50];const summ = numbers.reduce((acc, number) => acc + number, 0); // 150
Давайте пройдёмся и посмотрим пошагово, что происходит.
- В
reduce
передаётся функция, которая принимаетacc
(переменная-аккумулятор) иnumber
(текущий элемент массива). В качестве initialValue мы передаём 0; - При вызове для первого элемента
acc
будет равна 0, текущий элемент — 10. Соответственно, результатacc + number
будет равен 10.; - При вызове для следующего элемента
acc
уже будет равна 10, так как это не первый вызов и мы помним, что в этом случаеacc
равна результату предыдущего вызова. Соответственно результатacc + number
здесь будет10 + 20
— 30; - Дальше
acc
уже равна 30 и результат следующей итерации будет30 + 30
— 60; - Ну тут уже должно быть просто. Здесь
acc
равна 60 и результат60 + 40
— 100; - Последний шаг.
acc
равна 100. Результат100 + 50
— 150. И так как это последний элемент, то 150 и будет результатом выполненияreduce
.
Функция find
Здесь тоже название подсказывает. Данная функция даёт нам возможность найти элемент массива, соответствующий переданным условиям. Возвращается первый найденный элемент. Соответственно, использовать её целесообразно когда вы точно знаете, что нужный вам элемент в массиве в единственном числе.
Синтаксис
array.find(function(currentValue, index, arr), thisValue)
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
В качестве примера рассмотрим уже знакомый нам массив с рецептами. Положим, нам нужно найти рецепт омлета.
const omelet = recipes.find(recipe => recipe.title === "Омлет");
Функция every
Данная функция позволяет нам узнать соответствуют ли все элементы массива заданному условию. Если это так, функция возвращает true
. Если хоть один элемент не соответствует, то функция возвращает false
.
Синтаксис
array.every(function(currentValue, index, arr), thisValue)
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
Ну и пример. Самый распространённый вариант использования этой функции — проверка, что все поля формы заполнены. Проверим, что все поля имеют хотя бы один символ.
const formData = ['Иван', 'Иванов', 'ivan@mail.ru', ''];const validateForm = formData.every(field => field.length > 0); // false
Функция some
Данная функция позволяет нам узнать соответствует ли хотя бы один элемент массива заданному условию. Если это так, функция возвращает true
. Если ни один элемент не соответствует, то функция возвращает false
.
Синтаксис
array.some(function(currentValue, index, arr), thisValue);
Принимаемые аргументы
- currentValue – Обязательный аргумент. Текущий элемент массива;
- index – Опциональный аргумент. Индекс текущего элемента массива;
- arr – Опциональный аргумент. Оригинал массива;
- thisValue – Опциональный аргумент. Объект, который нужно использовать как
this
Допустим, у нас есть подборка рецептов. И мы хотим проверить есть ли там рецепты для вегетарианцев.
const recipes = [ { title: "Омлет", ingredients: [ "яйца", "сливки", "сливочное масло", "соль" ], isVegeterian: true }, { title: "Картофельное пюре", ingredients: [ "картофель", "сливочное масло", "молоко", "соль" ], isVegeterian: true }, { title: "Котлеты", ingredients: [ "говяжий фарш", "сухари панировочные", "яйца", "лук" ], isVegeterian: false }]const hasVegeterian = recipes.some(recipe => recipe.isVegeterian);
Ну вот и всё. Перечисленные функции существенно упрощают работу с массивами. Лидерами по полезности, конечно же, являются map
, filter
и reduce
. Я лично уже не представляю как раньше обходились без них.