前言
关于 forEach 和 map 会不会改变原数组的问题,之前也看过别人的总结,自己前几次遇到这个问题的时候觉得不是很清晰,有点纸上得来终觉浅的感觉,然后自己进行了一些小实践并分享出来。
测试开始
如果你们看到这篇文章,推荐将下面代码复制运行一下,个人认为会比看文字总结感受更加深刻。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>遍历</title>
</head>
<body>
<script>
let arr = [1, 2, 3, 4, 5]; // 普通数组;
let objArr = [{isChanged: false},{isChanged: false}]; // 对象数组;
// forEach 测试
let testForEach = function(){
// 普通数组测试
arr.forEach((item, index) => {
arr[index] = 0; // 这里 会 改变原数组 arr
item = 1; // 这里 不会 改变原数组 arr
console.log(typeof index); // index 为 number
})
console.log(arr); // [0, 0, 0, 0, 0] 而不是 [1, 1, 1, 1, 1]
// 对象数组测试
objArr.forEach((item, index) => {
// objArr[index] = 0; // 这里 会 改变原数组 objArr
item = 1; // 这里 不会 改变原数组 objArr
item.isChanged = true; // 这里 会 改变原数组 objArr,数组中元素的 isChanged 属性由 false 变为了 true
console.log(typeof index); // index 为 number
})
console.log(objArr); // [{isChanged: true},{isChanged: true}] 而不是 [1, 1]
}
// map 测试
let testMap = function(){
// 普通数组测试
let tempArr1 = arr.map((item, index) => {
item = 1; // // 这里 不会 改变原数组 arr
arr[index] = 0; // 这里 会 改变原数组 arr
console.log(typeof index); // index 为 number
return item + 1;
})
console.log(tempArr1); // map 返回数组 [2, 2, 2, 2, 2]
console.log(arr); // [0, 0, 0, 0, 0]
// 对象数组测试
let tempArr2 = objArr.map((item, index) => {
item.isChanged = true; // 这里 会 改变原数组 objArr,对象数组中元素的 isChanged 属性由 false 变为了 true
return item;
})
console.log('map 返回数组', tempArr2); // map 返回数组 [{isChanged: true},{isChanged: true}]
console.log('原对象数组', objArr); // [{isChanged: true},{isChanged: true}]
}
// reduce 这里顺便用一下 reduce,可以直接跳过
let testReduce = function(){
let accumulation = arr.reduce((preValue, curValue, index) => {
console.log(preValue, curValue, index); // index 为 curValue 的索引
return preValue + curValue;
}, 4);
// 这里initialValue 为 4,如果不传入第二个参数 initialValue,则 index 的值为 1,preValue 为数组索引为 0 的元素 array[0],否则为 array[1]
console.log(accumulation); // 19
}
// 测试函数调用
// testForEach();
// testMap();
// testReduce(); // 可忽略
</script>
</body>
</html>
forEach 与 map总结
forEach 和 map 它们都用于遍历数组,并且只会保证数组中元素的首地址不会改变,但该地址所指向的值可以改变(一般是引用类型数据)。即:
- 如果数组中的某个元素 item 为基本数据类型,在遍历过程中令 item = xxx ,那么原数组不会改变。
- 如果 item 为对象或者其他引用数据类型,令 item.x = xxx,那么此时原数组会被改变。
此外,在 forEach 和 map 中,通过 arr[index] = xxx 可以改变元素的首地址(原数组中的元素改变)。
forEach 和 map 均不能正确响应 continue 和 break;forEach 中 return 是直接返回,map 的 return 是返回新生成的数组对应某一项的元素,如果没有返回,则该项数组元素为 undefined。