map & forEach 都是从 es5 才开始出现,本文会讨论它们之间主要的区别以及如何使用它们。
简介
map & forEach 都是用来更方便地遍历数组的。
map 接收两个参数:callback 函数,它会在 map 执行之后被触发。上下文变量,即执行 callback 函数时 this 指向的对象。map 会返回一个新数组。
map(callback[, thisArg])
[1, 2, 3].map(function(value, index, originalArray) {
console.log(`${index}: ${value} / ${originalArray} /`);
console.log(this);
return value + 1;
}, { test: 1 });
// 0: 1 / 1,2,3 / {test: 1}
// 1: 2 / 1,2,3 / {test: 1}
// 2: 3 / 1,2,3 / {test: 1}
// 返回值:[2, 3, 4]
复制代码
注意:map 的返回不等于原数组:
const arr = [1];
const new_arr = arr.map(d => d);
arr === new_arr; // false
复制代码
forEach 接收的参数和 map 相同,但是它没有返回值,即它返回的是 undefined。
forEach(callback[, thisArg])
[1, 2, 3].forEach(function(value, index, originalArray) {
console.log(`${index}: ${value} / ${originalArray} /`);
console.log(this);
}, { test: 1 });
// 0: 1 / 1,2,3 / {test: 1}
// 1: 2 / 1,2,3 / {test: 1}
// 2: 3 / 1,2,3 / {test: 1}
// 返回值:undefined
复制代码
使用场景
因为 map & forEach 的主要区别是有无返回,所以,当你想基于一个原数组返回一个新数组,可以选择 map,当你只是想遍历数据不需要考虑返回时可以选择 forEach。
map
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 遍历数组时,每次都会返回一个值,如果没有显示返回,就返回 undefined,如 e.g.1。
const metrics = [
{ id: 'sales', selected: true, title: 'Sales'},
{ id: 'units', selected: true, title: 'Units'},
{ id: 'buyers', selected: false, title: 'Buyers'}
]
e.g.1
const ids = metrics.map(item => {
if(item.selected) {
return item.id
}
})
// ["sales", "units", undefined]
复制代码
在实际开发中我碰到这样一个逻辑:返回 metrics 中 selected:true 的元素的 id 组成的数组,因为想用一个函数搞定,然后就写了 e.g.2 这段代码,然鹅。。。可以选择用 e.g.3 / e.g.4 / e.g.5。
e.g.2
const ids = metrics.map(item => item.selected && item.id)
// ["sales", "units", false]
e.g.3
const ids = metrics.filter(item => item.selected).map(item => item.id)
e.g.4
const ids = []
metrics.forEach(item => {
item.selected && ids.push(item.id)
}
e.g.5
const ids = metrics.reduce((newArr, item) => {
item.selected && newArr.push(item.id)
return newArr;
}, []);
复制代码
速度对比
一些文章说 map 比 forEach 快,为了验证,我找了以下对比:
代码看起来差不多,但是结果却截然相反。一些 test cases 显示 forEach 快,一些显示 map 快。老实说,我也不确定,但是我觉的在现代 web 开发中不必纠结这点速度,代码的可读性更重要。
但有一点很确定,他们都比 for 循环慢。
结论
map & forEach 都是遍历可迭代对象的利器,可以简化代码,增加代码的可读性。我们只需区分使用它们的场景就行。
超值推荐:
阿里云双12已开启,云产品冰点价,新用户专享1折起,1核2G云服务器仅需89元/年,229元/3年。买了对于提升技术或者在服务器上搭建自由站点,都是很不错的,如果自己有实际操作,面试+工作中肯定是加分项。(老用户可以用家人或朋友的账号购买,真心便宜&划算)
可“扫码”或者“点击购买 "