Содержание
Данный метод, в отличии от ранее рассмотренного метода forEach(), вернет нам новый массив, при этом исходный массив не изменяется.
Синтаксис данного метода аналогичен методу forEach
callback
— функция, которая будет выполнена для каждого элемента массива.
Callback может быть стрелочной функцией и принимает такие параметры
currentValue
— значение текущего элемента массиваindex
— порядковый номер элемента (начиная с 0)currentArray
— массив, который мы перебираем
thisArg
— это необязательный параметр. Значение, используемое в качестве this
при вызове функции callback
.
Давайте рассмотрим простой пример:
const arr = [1, 2, 3];
const newArr = arr.map((item, index) => {
// увеличиваем значение каждого элемента на 1
// item - текущий элемент массива
return item + 1;
});
console.log(newArr); // [2, 3, 4]
console.log(arr); // [1, 2, 3]
В качестве callback
можно передать ранее созданную функцию:
const arr = [1, 2, 3];
function doThisForEachElement(item, index) {
return item + 1;
}
const newArr = arr.map(doThisForEachElement);
console.log(newArr); // [2, 3, 4]
Примеры использования метода map()
Теперь давайте рассмотрим еще несколько примеров.
Пример 1
Что будет если мы попробуем вернуть из колбека элементы по условию? Допустим из предыдущего примера, мы хотим вернуть только числа меньше или равные единице:
const arr = [1, 2, 3];
const newArr = arr.map(item => {
if (item <= 1) return item;
});
console.log(newArr); // [1, undefined, undefined]
В таком случае мы получим undefined
для значений, которые не прошли условие. Если вам нужно вернуть не все значения в новый массив, а только те что удовлетворяют условию — тогда используйте метод filter()
Пример 2
Продолжим с массивами чисел. Допустим, нам нужно вернуть в новый массив числа возведенные в определенную степень. Как делать возведение в степень в JavaScript рассматривали в другом посте.
const arr = [2, 4, 5, 7];
const newArr = arr.map(item => {
// возведем каждый элемент в третью степень
return item ** 3;
});
console.log(newArr); // [8, 64, 125, 343]
Также можно сделать упрощенный вариант записи, потому что мы сразу возвращаем измененное значение:
const newArr = arr.map(item => item ** 3);
Пример 3
Метод JS map() используется в React для рендеринга элементов. Вот как пример можете посмотреть код тут
const Todos = (todos) => {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
)
}
У нас есть массив todos
и на каждой итерации мы отрисовываем элемент li
Использование метода map() с объектами
Также мы можем использовать метод map() с массивом объектов и с самими объектами.
Пример 4
Допустим у нас есть массив пользователей и нам нужно провести определенные действия с каждым из пользователей — добавим свойство role
:
const users = [
{ id: 1, name: 'John', salary: 3000, position: 'developer' },
{ id: 2, name: 'Kate', salary: 2800, position: 'designer' },
{ id: 3, name: 'Bob', salary: 3200, position: 'manager' }
];
const newArray = users.map(item => {
item.role = 'admin';
return item;
});
// Будет возвращен новый массив со свойством 'role'
// для каждого пользователя
console.log(newArray); // { id: 1, ..., role: 'admin' }
В данном случае, если вы выведете в консоль массив users, то заметите что там тоже добавилось свойство role
Если нужно сохранить исходный массив неизменным, тогда нужно создать новый объект для этого и с помощью оператора spread скопировать свойства старого и добавить в него новые свойства:
const newArray = users.map(item => {
return { ...item, role: 'admin' }
});
// Останется неизменным
console.log(users);
// Новый массив со свойством 'role'
console.log(newArray);
Также можно задать условие и добавить разные свойства в зависимости от position
:
const users = [
{ id: 1, name: 'John', salary: 3000, position: 'developer' },
{ id: 2, name: 'Kate', salary: 2800, position: 'designer' },
{ id: 3, name: 'Bob', salary: 3200, position: 'manager' }
];
const newArray = users.map(item => {
if (item.position === 'manager') {
return { ...item, role: 'admin' }
}
return { ...item, role: 'user' }
});
// Role = admin будет добавлено только 3 пользователю
// У остальных role будет = user
console.log(newArray);
Или вот такая короткая запись с помощью тернарного оператора:
const newArray = users.map(item =>
item.position === 'manager' ? { ...item, role: 'admin' } : { ...item, role: 'user' }
);
Своя реализация метода map
let array = [1, 5, 10, 15];
Array.prototype.customMap = function (callback, thisArg) {
// Проверяем существует ли контекст вызова this (по умолчанию это сам массив)
if (this == null) {
throw new Error("It has to be array");
}
let context = this;
let obj = Object(this);
// Проверям кол-во переданных аргументов
// Если больше 1, значит был передан thisArg
if (arguments.length > 1) {
context = thisArg;
}
// Если callback это не функция, тогда выдаем оишбку
if (typeof callback !== "function") {
throw new Error("Callback has to be a function");
}
// Длинаа переданного масива
let len = obj.length;
let newArray = [];
let i = 0;
// Для каждого элемента массива вызываем callback
// И затем добавляем в массив, который в результат вернем
while (i < len) {
if (i in obj) {
newArray[i] = callback.call(context, this[i], i, obj);
}
i++;
}
return newArray;
};
// Теперь используем свой полифил
const newArray = array.customMap(number => number + 1);
console.log(newArray); // [2, 6, 11, 16]
Когда не следует использовать метод map()
Данный метод не следует использовать в таких случаях:
- Если вам нужен просто проход по массиву и вы не будете использовать возвращенный из данного метода массив. В таком случае лучше использовать forEach()
- Также когда функция (callback), которую вы передаете в качестве аргумента, не будет делать
return
let array = [1, 5, 10, 15];
const newArray = array.map((item) => {
item * 2; // не возвращается результат
});
console.log(newArray); // [undefined, undefined, undefined, undefined]