深入理解for,foreach,map的区别

如果你已经有使用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,而由于我们通过索引进行修改了匿名函数第三个参数,则导致原数组值也发生变化

总结:

  1. 都是用来遍历数组,forEach和map会为数组中每个元素执行回调函数。
  2. for循环是在确定数组的长度下使用,continue终止当前循环,break终止整个循环。
  3. map方法可以链式编程,但需要return。
  4. map:若数组的类型为值类型,则产生新的数组;若数组的类型为引用类型,则会改变原数组。
  5. forEach的基本原理就是for循环,返回值为undefined。
  6. forEach:若数组的类型为值类型,则不会改变原数组,若想改变原数组通过index这个参数来改变;若数组的类型为引用类型,则会改变原数组
  7. forEach()方法不会返回执行结果,而是undefined。forEach() 被调用时,不会改变原数组,也就是调用它的数组(尽管 callback 函数在被调用时可能会改变原数组)。
  8. map()方法会分配内存空间存储新数组并返回,map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。
相关推荐
Captaincc2 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师3 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen4 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒4 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow5 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8185 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800785 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明5 小时前
第 6 章 组件进阶
前端·vue.js
江华森5 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端
南青5 小时前
Vue 3 中后台实战:我踩过的 10 个坑和最佳实践
前端