1688网站特色,有什么超好用的做简历的网站,手机域名解析错误,网站维护费用一般多少钱目录
前言
一、forEach方法支持处理异步函数吗#xff1f;
二、forEach方法在循环过程中能中断吗#xff1f;
三、forEach 在删除自己的元素后能重置索引吗#xff1f;
四、forEach 的性能相比for循环哪个好#xff1f;
五、使用 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();
执行结果如下 我们在程序执行过程中可以发现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(); 运行结果 上面的代码片段在 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时中断foreachbreak;}const res await getSyncReq(item);console.log(队列${res}执行完成);});console.log(循环结束了);
};
const getSyncReq (x) new Promise((resolve, reject) {setTimeout(() {resolve(x);}, 1000 * x);});
forEachBreak();
执行结果 没错直接报错 因此forEach不能终止打断循环需要终止可以使用for循环实现。 三、forEach 在删除自己的元素后能重置索引吗 在 forEach() 中无法控制 index 的值它会无意识地增加直到大于数组长度跳出循环。因此也不可能通过删除自身来重置索引。来看一个简单的例子
let arrayNumbers [1, 2, 3, 4];
arrayNumbers.forEach((item, index) {console.log(item); // 1 2 3 4index;
}); 四、 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);// 计算时间戳差
我们来看结果 得出结论复杂的一些循环还是需要用到for循环效率更高。 五、 使用 forEach 会不会改变原来的数组 1.基本数据类型改变不了原数组
forEach不会直接改变数组。它是用于遍历数组的一种循环结构。在每次循环的过程中foreach会将数组中的每一个元素赋值给临时变量然后执行循环体内的代码。这个临时变量的值改变并不会直接影响原来的数组。如下案列
const array [1, 1, 1];array.forEach(a {a1
});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()等其他更高效的循环方法。
相比于forEachfor-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不必要只是为了判断是否交集可以做一个映射。 今天就介绍到这里啦是不是对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什么是点击劫持如何防御