如果你已经有使用JavaScript的经验,那你可能已经知道这两个看似相同的方法,深入解释了js中比较容易混淆的几种方法,重点在讲foreach和map 1. for方法
js for (语句1; 语句2; 语句3){ 被执行的代码块 } 语句1 (代码块)开始前执行 语句2 定义运行循环(代码块)的条件 语句3 在循环(代码块)已被执行之后执行
css
一般写法如下:
```js
for(var i = 0;i< arr.length;i++) {
}
这就是一个常见的,正序循环的for循环。这样写的缺点大家都明白:每次都从arr里取length与i来对比,浪费性能(而且,要是arr的长度是动态变化的,就会比较麻烦)。改进这个循环的办法是用变量保存arr.length
js
for(var i = 0, len = arr.length;i< len;i++) {
}
这样比第一种可以略微提升点性能,要是数组长,可以提升更多。 不过这样写就多了个变量,且这个变量只在用来与i对比的时候有用,看着有点鸡肋。 如果循环顺序对你不重要,那你可以尝试倒序循环:
js
for (var i = arr.length - 1; i >= 0; i--) {
}
注意语句2为定义运行循环的条件,第一个满足i>=0即可,第二个运行i-- ,并且只要 i 是真值,循环就会继续 ,所以i的开始值为arr.length-1
最后总结下提高for循环性能的要点: 1,适时break!不需要遍历全部的就要加跳出条件! 2,不要在for循环体里声明变量(建议一次var,多次赋值) 3,数组长度缓存,尽量少变量
2.map方法
js
//值类型,不改变原数组,形成新的数组
let valueArr = [11, 22, 33];
let newArray = valueArr.map(item => item * 2);
console.log(valueArr, newArray); //[11,22,33] [22,44,66]
//引用类型,改变原数组
let referArr = [{ width: 100 }, { width: 200 }];
referArr.map(item => item.editable = true);
console.log(referArr) //[{width:100,editable:true},{width:200,eidtable:true}]
3.forEach方法
js
//值类型,不改变原数组,返回值undefined
let valueArr = [11, 22, 33];
let newArray = valueArr.forEach(item => item * 2);
console.log(valueArr, newArray); //[11,22,33] undefined
//若要改变值,则需配合index来使用
let newArr1 = valueArr.forEach((item, index) => {
valueArr[index] = item * 2;
});
console.log(valueArr, newArray); //[22,44,66] undefined
//引用类型,改变原数组
let referArr = [{ width: 100 }, { width: 200 }];
referArr.forEach(item => item.editable = true);
console.log(referArr) //[{width:100,editable:true},{width:200,eidtable:true}]
注意点: 无论用forEach还是map遍历数组,用return来终止后面的语句是无效的,es6的forEach/map循环只能通过return中断当次循环
3.forEach 和 map 的共同点
- 都是循环遍历数组中的每一项
- 每一次执行匿名函数都支持三个参数,数组中的当前项item,当前项的索引index,原始数组input
- 匿名函数中的this都是指window
- 只能遍历数组
能用forEach()做到循环的,map()同样也可以做到循环。反过来也是如此。
4.差异点 1.map
有返回值,可以return出来一个length和原数组一致的数组(内容可能包含undefined、null等)
js
const array = [12,24,27,23,26];
const res = array.map((item,index,input) => {
return item*10;
})
console.log(res); // [120,240,270,230,260]
console.log(array); // [12,24,27,23,26]不变
- 参数:item数组中的当前项,index当前项的索引,input原始数组
- 区别:map的回调函数中支持return返回值,return的是一个数组,相当于把数组中的这一项进行改变(并不影响原来的数组,只是相当于把原数组克隆了一份,把克隆这一份的数组中的对应项改变了 );
2.forEach
没有返回值,返回结果为undefined
js
const array = [12,24,27,23,26];
const res = array.forEach((item,index,input) => {
return input[index] = item*10;
})
console.log(res); // undefined
console.log(array); // [120,240,270,230,260]原数组修改为变动后
- 参数:item数组中的当前项,index当前项的索引,input原始数组;
- 数组中有几项,那么传递进去的匿名回调函数就需要执行几次
- 理论上这个方式是没有返回值的,只是遍历数组中的每一项,不对原来数组进行修改,但是可以自己通过数组的索引来修改原来的数组
3.尝试使用map循环,通过索引进行修改原数组值
在没有返回值的情况下,执行map函数,通过修改索引的方式进行修改原数组
js
*const* array = [12,24,27,23,26];
const res = array.map((item,index,input) => {
input[index] = item*10;
})
console.log(res);
console.log(array);
通过以上代码,能够看到返回的结果长度仍然和原数组一致,但由于代码中没有执行return,则为undefined,而由于我们通过索引进行修改了匿名函数第三个参数,则导致原数组值也发生变化
总结:
- 都是用来遍历数组,forEach和map会为数组中每个元素执行回调函数。
- for循环是在确定数组的长度下使用,continue终止当前循环,break终止整个循环。
- map方法可以链式编程,但需要return。
- map:若数组的类型为值类型,则产生新的数组;若数组的类型为引用类型,则会改变原数组。
- forEach的基本原理就是for循环,返回值为undefined。
- forEach:若数组的类型为值类型,则不会改变原数组,若想改变原数组通过index这个参数来改变;若数组的类型为引用类型,则会改变原数组
- forEach()方法不会返回执行结果,而是undefined。forEach() 被调用时,不会改变原数组,也就是调用它的数组(尽管 callback 函数在被调用时可能会改变原数组)。
- map()方法会分配内存空间存储新数组并返回,map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。