关于前端面试中forEach方法的灵魂7问?

这篇具有很好参考价值的文章主要介绍了关于前端面试中forEach方法的灵魂7问?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

目录

前言

一、forEach方法支持处理异步函数吗?

二、forEach方法在循环过程中能中断吗?

三、forEach 在删除自己的元素后能重置索引吗?

四、forEach 的性能相比for循环哪个好?

五、使用 forEach 会不会改变原来的数组?

1.基本数据类型(改变不了原数组) 

2.引用类型(可以改变原数组) 

六、forEach能捕获异步函数中的错误吗?

七、forEach循环如何优化?

往期回顾 


前言

相信大家在工作或者面试中经常用foreach 方法,但你知道吗?forEach其实是for循环的一个特殊简化版,也叫增强for循环,forEach虽然是for循环的简化版本,但是并不是说forEach就比for更好用。废话不多说,下面我们一步步解开这7点疑问。

一、forEach方法支持处理异步函数吗?

首先forEach方法不支持处理异步函数,我们来详细看下如下代码

const forEachFun = async () => {
  console.log("循环开始了了");
    let queue = [3, 2, 1];
    queue.forEach(async (item) => {
        const res = await getSyncReq(item);
        console.log(`队列${res}执行完成`);
    });
    console.log("循环结束了");
};
const getSyncReq = (x) =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(x);
        }, 1000 * x);
    });
forEachFun();

执行结果如下

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

我们在程序执行过程中可以发现forEach() 无法等待异步函数完成,它将继续执行下一个项目。这意味着,如果在 forEach() 中使用异步函数,则无法保证异步任务的执行顺序。

那么如果我们想在循环中使用异步函数该怎么处理呢?

其实javascript中提供了很多函数,支持返回promise,比如map函数,filter函数,reduce函数,还有我们经常使用的for循环,都能达到预期效果,下面我们以for循环为案例,其他函数根据使用场景大同小异。

const forFun = async () => {
  console.log("循环开始了了");
    let queue = [1, 2, 3];
    for (let i = 0; i< queue.length; i++) {
      const res = await getSyncReq(queue[i]);
      console.log(`队列${res}执行完成`);
    }
    console.log("循环结束了");
};
const getSyncReq = (x) =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(x);
        }, 1000 * x);
    });
forFun();

 运行结果

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

上面的代码片段在 async 函数中使用了 await 关键字,for循环会等待 async 函数完成并返回结果,实现了整个异步请求的同步执行。

二、 forEach方法在循环过程中能中断吗?

forEach() 方法不支持使用 break 或 continue 语句来中断循环或跳过项目。如果需要跳出循环或跳过某个项目,则应使用 for 循环或其他支持 break 或 continue 语句的方法。下面我们看一段代码

const forEachBreak = async () => {
  console.log("循环开始了了");
    let queue = [3, 2, 1];
    queue.forEach(async (item) => {
      if (item === 2) { // 条件为2时中断foreach
        break;
      }
      const res = await getSyncReq(item);
      console.log(`队列${res}执行完成`);
    });
    console.log("循环结束了");
};
const getSyncReq = (x) =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(x);
        }, 1000 * x);
    });
forEachBreak();

执行结果

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

没错!直接报错 !

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

因此forEach不能终止打断循环,需要终止可以使用for循环实现。 

三、forEach 在删除自己的元素后能重置索引吗?

在 forEach() 中,无法控制 index 的值,它会无意识地增加,直到大于数组长度,跳出循环。因此,也不可能通过删除自身来重置索引。来看一个简单的例子:

let arrayNumbers = [1, 2, 3, 4];
arrayNumbers.forEach((item, index) => {
    console.log(item); // 1 2 3 4
    index++;
});

四、 forEach 的性能相比for循环哪个好?

先说答案,for循环的性能要高于forEach,我们用代码来测试一下

// 构建长度为20000的数组
const arrars = Array.from({ length: 20000 })

// 记录for开始时间 for循环计算
const forStart = +new Date();
for(let i = 0;i< arrars.length;i++) {
  console.log('for循环');
}
// 记录for结束时间
const forEnd = + new Date();
console.log('for循环20000次时间', forEnd - forStart); // 计算时间戳差


// 记录forEach开始时间 forEach循环计算
const forEachStart = +new Date();
arrars.forEach((item, index) => {
  console.log('forEach循环');
})
// 记录forEach结束时间
const forEachEnd = +new Date();
console.log('forEach循环20000次时间', forEachEnd - forEachStart);// 计算时间戳差

我们来看结果

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

得出结论:复杂的一些循环还是需要用到for循环效率更高。 

五、 使用 forEach 会不会改变原来的数组?

1.基本数据类型(改变不了原数组) 

forEach不会直接改变数组。它是用于遍历数组的一种循环结构。在每次循环的过程中,foreach会将数组中的每一个元素赋值给临时变量,然后执行循环体内的代码。这个临时变量的值改变并不会直接影响原来的数组。如下案列

const array = [1, 1, 1];

array.forEach(a => {
    a+1
});

console.log(array);//[1,1,1]

2.引用类型(可以改变原数组) 

如果临时变量是通过引用传递的,所以在循环体内对临时变量进行的修改会反映在原始数组中。如下案列

const obj = [
    {
        a : 'Tom',
        b : 22
    },
    {
        a : 'BOb',
        b : 33
    }
]

obj.forEach(aa => {
    if(aa.a === 'Tom') {
        aa.b = 23
    }
})

console.log(obj);//[{"a":"Tom","b":23},{"a":"BOb","b":33}]

那么为啥会发生引用类型可以改变原数组,但是原数组改变不了原数组呢?

那是因为基本类型在栈内存中直接存储变量与值,而引用类型的真正数据是保存在堆内存,栈内只保存了对象的变量以及对应的堆的地址,所以操作Object其实就是直接操作了原数组对象本身。

六、forEach能捕获异步函数中的错误吗?

如果异步函数在执行时抛出错误,使用 forEach() 是无法捕获该错误。这意味着即使 async 函数发生错误,forEach() 也会继续执行。

七、 forEach循环如何优化?

可以使用JS的for循环代替foreach进行双重循环,因为for循环的效率较高。另外,如果双重循环需要对数组进行操作,可以使用数组的一些高阶方法(如map、filter、reduce等)来替代循环,进一步提高效率。同时,还可以考虑将数据进行预处理,以减少循环次数。我们来看一个简单的forEach双重循环的优化。

需求:

将选中的数据中的count值更新给全量数据,思路是找出全量数据id对应的数据,然后将选中更新后的count值赋值给全量数据的count,实现全量数据的部分数据更新。

原代码

// 全部数据
let allData = [
  {
    id: 1,
    count: 1
  },
  {
    id: 2,
    count: 2
  },
  {
    id: 3,
    count: 3
  },
  {
    id: 4,
    count: 4
  },
]

// 选中数据
let selectData = [
  {
    id: 2,
    count: 22
  },
  {
    id: 4,
    count: 444
  },
]
// 找出选中数据并且更新count值
allData.forEach(item => {
  selectData.forEach(list => {
    if (item.id === list.id) {
      item.count = list.count;
    }
  })
})
console.log(allData)

这个双重forEach如何优化呢?我们可以使用for-of循环或者Array.prototype.map()等其他更高效的循环方法。

相比于forEach,for-of循环、Array.prototype.map()等方法会有更好的性能表现。因为它们直接迭代数组的索引值,而不需要创建新的函数上下文。示例代码如下所示:

双map优化

// 全部数据
let allData = [
  {
    id: 1,
    count: 1
  },
  {
    id: 2,
    count: 2
  },
  {
    id: 3,
    count: 3
  },
  {
    id: 4,
    count: 4
  },
]
 
// 选中数据
let selectData = [
  {
    id: 2,
    count: 22
  },
  {
    id: 4,
    count: 444
  },
]
 
const newSelect = Object.fromEntries(
  selectData.map(({ id, count }) => [id, { count }])
)
const newAllData = allData.map(s =>  {
  s.id in newSelect && (s.count = newSelect[s.id].count);
  return s;
})
console.log(newAllData)

for-of和map结合循环优化 

// 全部数据
let allData = [
  {
    id: 1,
    count: 1
  },
  {
    id: 2,
    count: 2
  },
  {
    id: 3,
    count: 3
  },
  {
    id: 4,
    count: 4
  },
]
 
// 选中数据
let selectData = [
  {
    id: 2,
    count: 22
  },
  {
    id: 4,
    count: 444
  },
]

for (let item of allData) {
  item.id in newSelect && (item.count = newSelect[item.id].count);
}
console.log(allData)

我们用map构造新的数组,id为key值,value值为选中项,然后通过一层map循环或者for-of循环实现对部分全量数据的更新,源代码外层的forEach不必要,只是为了判断是否交集可以做一个映射。 

在接口中获取数据时,想获取数组里面嵌套另外一个数组的数据的时候,需要使用foreac,JavaScript,javascript,foreach,foreach性能,foreach异常,foreach优化,foreach异步

今天就介绍到这里啦!是不是对forEach函数有了进一步的认识?希望能在面试或工作中帮到大家!有不足之处,大家补充,如果文章对你有所帮助,❤️关注+点赞❤️鼓励一下博主会持续更新。。。。

我的个人博客:https://code-nav.top

往期回顾 

Javascript 地狱级的if else / switch case该如何优化?

 css实现元素居中的6种方法 

Angular8升级至Angular13遇到的问题

前端vscode必备插件(强烈推荐)

Webpack性能优化

vite构建如何兼容低版本浏览器

前端性能优化9大策略(面试一网打尽)!

vue3.x使用prerender-spa-plugin预渲染达到SEO优化

 vite构建打包性能优化

 vue3.x使用prerender-spa-plugin预渲染达到SEO优化

 ES6实用的技巧和方法有哪些?

 css超出部分显示省略号

vue3使用i18n 实现国际化

vue3中使用prismjs或者highlight.js实现代码高亮

什么是 XSS 攻击?什么是 CSRF?什么是点击劫持?如何防御文章来源地址https://www.toymoban.com/news/detail-808855.html

到了这里,关于关于前端面试中forEach方法的灵魂7问?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 报错forEach,其实是forEach之前的数据未获取到--TypeError: Cannot read properties of undefined (reading ‘forEach‘)

    跑了个js,测试时F12报错 报错如下: Uncaught TypeError: Cannot read properties of undefined (reading \\\'forEach\\\')     at 报错代码如下 forEach其实类似于for i in xxx中逐个取出数据,所以报错那可能性前面的box_geo1.faces未获取到数据而导致,因而加行代码验证下,console.log(\\\'faces信息\\\',box_geo1.faces); 于

    2024年02月13日
    浏览(44)
  • 关于前端数据Fail to load response data解决方法

    \\\"Failed to load response data:\\\" 这个错误通常是由于请求的资源没有被正确加载或者没有找到。这可能是由于以下几种原因导致的: 资源路径错误 : 确保你请求的资源路径是正确的。检查一下你的代码,确保你指定的路径是准确的,并且资源确实存在于该路径。 资源不存在或者路径

    2024年02月04日
    浏览(61)
  • 前端面试——关于this指向问题?

    想要知道关于this的指向问题,首先要了解this的绑定规则。那么this到底是什么样的绑定规则呢?一起来研究一下吧! 绑定一:默认绑定 绑定二:饮食绑定 绑定三:显示绑定 绑定四:隐式绑定 什么情况下使用默认绑定呢?独立函数调用。独立的函数调用我们可以理解成函数

    2024年01月25日
    浏览(47)
  • web前端Javascript—7道关于前端的面试题

    本文主要是web前端Javascript—的面试题,附上相关问题以及解决答案,希望对大家web前端Javascript闭包的学习有所帮助。 每个JavaScript 程序员都必须知道闭包是什么。在 JavaScript 面试中,你很可能会被问到的问题 以下是 7 个有关 JavaScript的面试题,比较有挑战性。不要查看答案

    2024年02月03日
    浏览(101)
  • 前端关于学习方式,解决问题的面试题(本人真实面试题)

    本文旨在 为大家平时面试解答提供思路 和 介绍平时学习,解决问题的方法。 1、如何解决Echarts难使用的问题 深入学习文档: ECharts 的官方文档是非常详细和全面的。仔细阅读文档,深入理解配置项和 API,可以帮助你更好地使用 ECharts。 查看示例和案例: ECharts 官方网站提

    2024年01月21日
    浏览(75)
  • 关于Vue前端接口对接的思考

    Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive. happy for hardess to solve denpendies. 需求: 1.vue 组件分类和获取数值的方式 在Vue中,组件可以分为以下几种类型: 全局组件(Global Components):全局组件是在

    2024年01月23日
    浏览(45)
  • 关于怎么用好API接口获取更多信息节约时间成本

      API接口是现代互联网应用开发的重要工具,它允许开发者使用标准化的方式获取数据和服务,在搭建应用中扮演了重要的角色。因此,如何利用API接口获取更多信息已经成为了每个开发者需要掌握的技能之一。 第一步:寻找 API接口 在开始使用API接口前,首先要确定需要获

    2024年02月06日
    浏览(61)
  • 面试官:请问蓝牙设备如何测试?灵魂拷问,我人傻了....

    所谓蓝牙技术,实际上是一种短距离无线通信技术,利用“蓝牙”技术,能够有效地简化掌上电脑、笔记本电脑和移动电话手机等移动通信终端设备之间的通信,也能够成功地简化以上这些设备与Internet之间的通信,从而使这些现代通信设备与因特网之间的数据传输变得更加

    2023年04月11日
    浏览(43)
  • 来一场关于元宇宙的灵魂辩论|BOOK DAO内容共建招募

    「 备选问题  」 1. 你认为元宇宙最重要的特点是什么?用一句话描述你理解的 “元宇宙” 2. 元宇宙是游戏2.0吗?它与游戏有什么不同? 3. 元宇宙是否需要区块链?是否需要NFT?各扮演什么角色? 4. 元宇宙是否需要经济系统,如果需要,如何设计? 5. 在元宇宙中,你如何证

    2024年01月21日
    浏览(41)
  • vue3【侦测|过滤|数组方法】数据变化侦测&&信息筛选过滤&&常用数组方法.filter() .map() .forEach(). find()

    内容回顾 点击快速复习v-for👏👏👏。本期内容主要是 数据变化的检测 和 信息的过滤筛选 以及 常用的数组方法 👇 ( .filter() 、 .map() 、 .forEach() 、 .find() 、 .findIndex() 、 .some() 、 .every() 、 .fill() )。 延展一下 :👏👏👏 关于数据的变化——比如,对表格数据进行的搜索,

    2024年02月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包