источник:medium.com/better-pro Страна…
Автор: Луна
Перевод: Официальный аккаунт "Full-Stack Front-End Developer"
Одни из самых популярных функций в JavaScript — это, вероятно, map и forEach. Они существуют со времен ECMAScript 5 (сокращенно es5).
В этой статье я расскажу об основных различиях между ними и покажу вам несколько примеров их использования.
Перед чтением
По сути, итерация объекта в JavaScript зависит от того, является ли объект итерируемым или нет. По умолчанию массивы являются итерируемыми.map
иforEach
включен вArray.prototype
, поэтому нам не нужно учитывать итерируемость. Если вы хотите узнать больше, я рекомендую вам взглянуть на то, что такое итерации в JavaScript!
Что такое map() и forEach()?
map
иforEach
это вспомогательный метод в массиве, чтобы легко перебирать массив. Мы использовали цикл по массиву, как показано ниже, без каких-либо вспомогательных функций.
var array = ['1', '2', '3'];
for (var i = 0; i < array.length; i += 1) {
console.log(Number(array[i]));
}
// 1
// 2
// 3
Он существует с начала эры JavaScript.for
цикл. Он содержит 3 выражения: начальное значение, условие и конечное выражение.
Это классический способ перебора массива. Начиная с ECMAScript 5 новые функции, кажется, делают нас счастливее.
map
map
роль иfor
Шлейф точно такой же, толькоmap
Создается новый массив, что приводит к вызову предоставленной функции для каждого элемента в вызывающем массиве.
Он принимает два параметра: один вызывается позжеmap
илиforEach
Функция обратного вызова вызывается, когда вызывается другая функция, когда вызывается функция обратного вызоваthisArg
переменные контекста.
const arr = ['1', '2', '3'];
// 回调函数接受3个参数
// 数组的当前值作为第一个参数
// 当前值在数组中的位置作为第二个参数
// 原始源数组作为第三个参数
const cb = (str, i, origin) => {
console.log(`${i}: ${Number(str)} / ${origin}`);
};
arr.map(cb);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
Функцию обратного вызова можно использовать следующим образом.
arr.map((str) => { console.log(Number(str)); })
map
Результат не равен исходному массиву.
const arr = [1];
const new_arr = arr.map(d => d);
arr === new_arr; // false
Вы также можете использовать объект какthisArg
перешли на карту.
const obj = { name: 'Jane' };
[1].map(function() {
// { name: 'Jane' }
console.dir(this);
}, obj);
[1].map(() => {
// window
console.dir(this);
}, obj);
объектobj
статьmap
изthisArg
. Но функция обратного вызова стрелки не можетobj
как егоthisArg
.
Это связано с тем, что стрелочные функции отличаются от обычных функций.
forEach
forEach
это еще одна функция цикла для массивов, ноmap
иforEach
разные в использовании.map
иforEach
Можно использовать два параметра - функцию обратного вызова иthisArg
, которые используются в качестве ихthis
.
const arr = ['1', '2', '3'];
// 回调函数接受3个参数
// 数组的当前值作为第一个参数
// 当前值在数组中的位置作为第二个参数
// 原始源数组作为第三个参数
const cb = (str, i, origin) => {
console.log(`${i}: ${Number(str)} / ${origin}`);
};
arr.forEach(cb);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
Какая разница?
map
возвращает новый массив исходного массива, ноforEach
Но это не так. Но оба они обеспечивают неизменность исходного объекта.
[1,2,3].map(d => d + 1); // [2, 3, 4];
[1,2,3].forEach(d => d + 1); // undefined;
Если вы измените значение внутри массива,forEach
Неизменяемость массивов не гарантируется. Этот метод гарантирует неизменяемость только в том случае, если вы не трогаете ни одно из значений внутри.
[{a: 1, b: 2}, {a: 10, b: 20}].forEach((obj) => obj.a += 1);
// [{a: 2, b: 2}, {a: 11, b: 21}]
// 数组已更改!
Когда использовать map() и forEach()?
Поскольку основное различие между ними заключается в том, есть ли возвращаемое значение, вы захотите использоватьmap
чтобы создать новый массив и использоватьforEach
Просто для отображения на массив.
Вот простой пример.
const people = [
{ name: 'Josh', whatCanDo: 'painting' },
{ name: 'Lay', whatCanDo: 'security' },
{ name: 'Ralph', whatCanDo: 'cleaning' }
];
function makeWorkers(people) {
return people.map((person) => {
const { name, whatCanDo } = person;
return <li key={name}>My name is {name}, I can do {whatCanDo}</li>
});
}
<ul>makeWorkers(people)</ul>
Например, в Реактеmap
это очень распространенный способ изготовления элементов, потому чтоmap
После обработки данных исходного массива создается и возвращается новый массив.
const mySubjectId = ['154', '773', '245'];
function countSubjects(subjects) {
let cnt = 0;
subjects.forEach(subject => {
if (mySubjectId.includes(subject.id)) {
cnt += 1;
}
});
return cnt;
}
countSubjects([
{ id: '223', teacher: 'Mark' },
{ id: '154', teacher: 'Linda' }
]);
// 1
С другой стороны, если вы хотите что-то сделать с данными, не создавая новый массив,forEach
Очень полезно. Кстати, вы можете использоватьfilter
Пример с рефакторингом.
subjects.filter(subject => mySubjectId.includes(subject.id)).length;
Подводя итог, я бы рекомендовал вам использовать карту при создании нового массива и forEach, когда вам не нужно создавать новый массив, а что-то делать с данными.
сравнение скорости
В некоторых постах упоминаетсяmap
СравниватьforEach
быстрый. Итак, мне любопытно, правда ли это. Я нашел это сравнение.
Код выглядит очень похоже, но результат противоположный. некоторые тесты говорятforEach
быстрее, говорят некоторыеmap
Быстрее. Может быть, ты говоришь себеmap/forEach
Быстрее других, возможно, вы правы. Честно говоря, я не уверен. Я думаю, что в современной веб-разработке удобочитаемость важнее, чемmap
иforEach
Скорость между ними гораздо важнее.
Но одно можно сказать точно — оба лучше, чем встроенный JavaScript.for
Циклы медленные.