Map, Filter и Reduce в JavaScript
Синтаксис для map
показан ниже.
array.map(function(currentValue, index, arr), thisValue)
// return element for newArray, after executing something
Метод map()
создает новый массив и выполняет функцию над каждым элементом массива.
Под капотом, map
передает три аргумента в обратный вызов:
- текущий элемент в массиве
- индекс массива текущего элемента
- весь массив, для которого вы вызвали map.
Давайте посмотрим на некоторый код
map в примере
// Durations are in minutes
const tasks = [
{
'name' : 'Write for Learning',
'duration' : 120
},
{
'name' : 'Work out',
'duration' : 60
},
{
'name' : 'Watching Movie',
'duration' : 60
}
];
Допустим, мы хотим создать новый массив, содержащий только имя каждой задачи, чтобы мы могли просмотреть все, что мы сделали сегодня. Используя цикл for, мы напишем что-то вроде этого:
const task_names = [];
for (let i = 0; i < tasks.length; i +=1){
task_names.push(tasks[i].name)
}
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
JavaScript также предлагает цикл forEach
. Он функционирует так же, как цикл for, но управляет всеми сложностями, связанными с проверкой индекса цикла на длину массива:
const task_names = [];
tasks.forEach(function (task) {
task_names.push(task.name);
});
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Используя map, мы можем просто написать:
const task_names = tasks.map(function (task, index, array) {
return task.name;
});
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Еще более лаконичным способом написания map
в современном JavaScript является использование стрелочных функций
const task_names = tasks.map(task => task.name)
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Стрелочные функции — это краткая форма для однострочных функций, которые содержат только оператор возврата.
let map = function (array, callback) {
const new_array = [];
array.forEach(function (element, index, array) {
new_array.push(callback(element));
});
return new_array;
};
Этот код принимает в качестве аргументов массив и функцию обратного вызова. Затем он создает новый массив, выполняет функцию обратного вызова на каждом элементе переданного массива, заносит результаты в новый массив и возвращает новый массив.
Подробнее
Фильтр
Делает именно то, что звучит: Берет массив и отфильтровывает ненужные элементы.
Синтаксис для filter следующий:
array.filter(function(currentValue, index, arr), thisValue)
// return element for newArray, if true
const words = ['Python', 'Javascript', 'Go', 'Java', 'PHP', 'Ruby'];
const result = words.filter(word => word.length < 8);
console.log(result);
Используя forEach
, мы бы написали:
const difficult_tasks = [];
tasks.forEach(function (task) {
if (task.duration >= 120) {
difficult_tasks.push(task);
}
});
console.log(difficult_tasks)
Используя filter
, мы можем просто написать:
const difficult_tasks = tasks.filter((task) => task.duration >= 120 );
console.log(difficult_tasks)
- избежать изменения массива внутри цикла
forEach
илиfor
- присваивать его результат непосредственно новой переменной, а не заталкивать в массив, который мы определили в другом месте.
Уменьшить
уменьшить на практике
let numbers = [1, 2, 3, 4, 5],
total = 0;
numbers.forEach(function (number) {
total += number;
});
console.log(total); // 15
Хотя это не плохой вариант использования forEach
, reduce
все же имеет преимущество, позволяя нам избежать мутации. Используя reduce
, мы бы написали:
const total = [1, 2, 3, 4, 5].reduce(function (previous, current) {
return previous + current;
}, 0);
console.log(total); // 15
Сначала мы вызываем reduce
для нашего списка чисел. Мы передаем ему обратный вызов, который принимает в качестве аргументов предыдущее и текущее значения и возвращает результат их сложения. Поскольку мы передали 0
в качестве второго аргумента reduce
, на первой итерации он будет использовать это значение в качестве previous
.
С помощью стрелочных функций мы могли бы написать это следующим образом:
const total = [1, 2, 3, 4, 5].reduce((previous, current) => previous+current),0;
console.log(total) // 15
Если мы сделаем шаг за шагом, это будет выглядеть следующим образом:
Другой пример
let num1 = [2, 3, 4, 5, 6, 7];
let num4 = num1.reduce(sum)
function sum(total, value){
return total + value;
}
document.getElementById("demo").innerHTML = num4; // 27