深聊JS数组中的forEach和map方法

2019-03-13  本文已影响34人  空无一码

在和团队分享Airbnb的eslint规则时,当我们讨论 no-param-reassign 的时候,在项目的代码中用到了forEach 方法,场景如下:

const demoFunc = (arr) => {
  arr.forEach((item) = > {
    item.name = 'coder';
  });  
}

因为改变了函数的形参,所以报了eslint的错误,这引起了我们对forEach方法的重视,同时也让我们想到了另一很类似的map方法,对于有追求的码农,当然要写篇文章深入剖析有关的知识。

forEach()和map()两个方法都是ECMA5中Array引进的新方法,主要作用都是对数组的每个元素执行一次提供的函数,但他们还是有区别的。

map()

map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

const arr = [1, 2, 3];
const newArr = arr.map(item => item + 1);

console.log(arr); // [ 1, 2, 3 ]
console.log(newArr); // [ 2, 3, 4 ]

上面代码中,arr数组的所有成员依次执行参数函数,运行结果组成一个新数组返回,原数组没有变化。

forEach()

forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。

这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。

const arr = [1, 2, 3];
const newArr = arr.forEach(item => item + 1);

console.log(arr); // [ 1, 2, 3 ]
console.log(newArr); // undefined

可以看到,newArr为undefined,说明forEach方法不返回值。

注意,forEach方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用for循环。

forEach和map方法 能改变原数组吗?

可以看到上面的例子,对于数组元素为基础类型的数组,forEach和map方法 并不能改变原数组,但是当元素为对象时:

const arr = [{ name: 'coder' }, { name: 'coder' }, { name: 'coder' }];
const newArr = arr.forEach(item => item.name = 'newName');

console.log(arr); 
// [ { name: 'newName' }, { name: 'newName' }, { name: 'newName' } ]
console.log(newArr);  // undefined

可以看到,对于元素为对象的数组,再使用forEach()方法时,虽然依然没有返回值,但原数组的元素却是可以改变的。

const arr = [{ name: 'coder' }, { name: 'coder' }, { name: 'coder' }];
const newArr = arr.map(item => item.name = 'newName');

console.log(arr); 
// [ { name: 'newName' }, { name: 'newName' }, { name: 'newName' } ]
console.log(newArr);  
// [ 'newName', 'newName', 'newName' ]

可以看到,对于元素为对象的数组,再使用map()方法时,原数组的元素也是可以改变的,但是返回的新数组却不是由对象元素组成的。

结语

可以看到,即使是我们常用到的forEach和map方法,也是有很多可以深入的地方,特别是当数组元素为引用类型时,是可以改变数组本身的。

而且map()方法返回的新数组和原数组也是有区别的,可见eslint的代码检查则能提醒我们要清楚知道自己所写代码的意图,防止未知错误的发生。

上一篇 下一篇

猜你喜欢

热点阅读