1.forEach
(1)forEach()方法从到至尾遍历数组,为每个元素调用指定的函数;
(2)forEach()无法在所有元素有传递给调用的函数之前终止遍历;
(3)如果要提前终止,必须把forEach()方法放在一个try块中,并能抛出一个异常 。
//传递的函数作为forEach()的第一个参数
//然后forEach()使用三个参数调用该函数:数组元素、元素的索引和数组本身
let arr = [1, 2, 3, 4, 5];
arr.forEach((v, i, a) => a[i] = v * v);
console.log(arr);//=>[1,4,9,16,25]
//如果只关心数组的值,可以编写只有一个参数的函数,额外的参数将忽略
let arr1 = [1, 2, 3, 4, 5];
let sum = 0;
arr1.forEach(item => sum += item);
console.log(sum);//=>15
//如果forEach()调用的函数抛出foreach.break异常,循环会提前终止
function foreach(a, f, t) {
try {
a.forEach(f, t);
} catch (e) {
if (e === foreach.break) return;
else throw e;
}
}
foreach.break = new Error("StopIteration");
2.map()
(1)map()方法将调用的数组的每个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值;
(2)map()返回的是新数组,它不修改调用的数组;
(3)如果是稀疏数组,返回的也是相同的稀疏数组:它具有相同的长度,相同的缺失元素。
let arr = [1, 2, 3];
let b = arr.map(item => item * 2);//arr是[1, 2, 3];b是[2, 4, 6]
3.区别(重点)
(1)关于返回值
forEach():没有返回值,用console.log()打印是undefined。
map():有返回值,返回的是一个新数组(注意,不是函数的返回值),它包含函数的返回值。
let arr1 = [1, 2, 3];
let a = arr1.forEach((v, i, a) => a[i] = v * v);
console.log(a);//=>undefined;没有返回值
console.log(arr1);//=>[1, 4, 9];原数组会改变
let arr2 = [1, 2, 3];
let b = arr2.map(v => v * v);
console.log(b);//=>[1, 4, 9];返回新数组
console.log(arr2);//=>[1, 2, 3];原数组不会改变
(2)关于函数的参数(划重点,仔细看!
)
a.当函数的参数是3个(数组元素、元素的索引和数组本身)时,forEach()和map()的区别参照上面;
b.当函数的参数只有1个(数组元素)时,forEach()和map()的区别就大不相同
了。
let arr1 = [1, 2, 3];
let a = arr1.forEach(item=>item+1);
console.log(a);//=>undefined;没有返回值
console.log(arr1);//=>[1, 2, 3];原数组不会改变
let arr2 = [1, 2, 3];
let b = arr2.map(item=>item+1);
console.log(b);//=>[2, 3, 4];返回新数组
console.log(arr2);//=>[1, 2, 3];原数组不会改变
我们可以看到,当用1个参数时,forEach()改变数组的值是没有效果的。
我们来看一种错误写法:
let arr1 = [1, 2, 3];
let a = arr1.forEach(function (item) {
item = item + 1
});
console.log(a);//=>undefined;没有返回值
console.log(arr1);//=>[1, 2, 3];原数组不会改变
因为传入的参数不可能既在左值里,又在右值里,这种赋值关系本身就是一种错误。
那么这样呢:
let arr1 = [1, 2, 3];
let a = arr1.forEach(function (item) {
return item + 1
});
console.log(a);//=>undefined;没有返回值
console.log(arr1);//=>[1, 2, 3];原数组不会改变
其实,函数本身是可以有返回值的,只是当只有1个参数时,forEach()没有办法使自身数组某个位置的值改变后,再赋值给该位置的元素。
我们来看:
let arr1 = [1, 2, 3];
let arr2 = [];
let a = arr1.forEach(function (item) {
arr2.push(item + 1)
});
console.log(a);//=>undefined;没有返回值
console.log(arr1);//=>[1, 2, 3];原数组不会改变
console.log(arr2);//=>[2, 3, 4];arr2拿到了经过处理的值
forEach()改变自身数组的时候是3个参数:通过数组本身调用索引确定位置,再通过将改变后的值赋值给该位置的元素来改变自身。
当只有一个参数时,map()也是因为赋值给了新数组,才看起来像是改变了原数组而已,其实原数组并没有改变。
let arr1 = [1, 2, 3];
let a = arr1.map(item=>item-1);
console.log(a);//=>[0, 1, 2];a是新数组
console.log(arr1);//=>[1, 2, 3];原数组不会改变
当是3个参数时,map()可以改变原数组,但返回的依然是新数组。
let arr1 = [1, 2, 3];
let a = arr1.map((v, i, a) => a[i] = v + 1);
console.log(a);//=>[2,3,4];a依然是新数组
console.log(arr1);//=>[2,3,4];原数组改变了
不信?我们来看:
let arr1 = [1, 2, 3];
let a = arr1.map((v, i, a) => a[i] = v + 1);
console.log(a);//=>[5,3,4];a依然是新数组
console.log(arr1);//=>[2,3,4];原数组改变了
a[0] = 5;//赋值
console.log(a);//=>[5,3,4];a是原数组
console.log(arr1);//=>[2,3,4];原数组改变了
当重新赋值时,我们就能看到区别。a确实指向一个与arr1不同的数组。但为什么两个位置都变成5了呢?因为a本身是一个变量,它保存的并不是数组,而是一个指针。我们知道,数组是引用数据类型,变量只是保存了一个能找到它的地址,并且,大家找到的都是同一个。所以,一个地方改变了它,其他地方找到的也是改变之后的它。