详解JS中你不知道的各种循环测速(详解JS中你不知道的各种循环测速)
详解JS中你不知道的各种循环测速
详解JS中你不知道的各种循环测速目录
- 前言
- 1. for 循环
- 2. while 循环和 do-while 循环
- 3. forEach、map 和 reduce 循环
- 3.1 forEach 的简要介绍
- 3.2 forEach 等的测速
- 4. for-of
- 4.1 for-of 的简要介绍
- 4.2 for-of 的循环测速
- 5. for-in 循环
- 6. 总结
在测试循环速度之前,我们先来创建一个有 100 万数据的数组:
const len = 100 * 10000; const arr = []; for (let i = 0; i < len; i++) { arr.push(Math.floor(Math.random() * len)); }
测试环境为:
1.电脑:iMac(10.13.6);
2.处理器:4.2 GHz Intel Core i7;
3.浏览器:Chrome(89.0.4389.82)
1. for 循环for 循环是我们最常用的一种循环方式了,最大的好处就是结构清晰,能够随时 break 停止。
我们先用 10 次的测试来看下:
console.log('test for'); for (let k = 0; k < 10; k++) { console.time('for'); let sum = 0; for (let i = 0; i < len; i++) { sum += arr[i] % 100; } console.timeEnd('for'); }
最终得到的结果:
在第 1 次和第 2 次时耗时比较多,从第 3 次开始就一直维持在 1.25ms 左右。
2. while 循环和 do-while 循环
这两个放在一起,也是他们的结构足够像,而且也能够随时 break 停止。
console.log('\ntest while'); for (let k = 0; k < 10; k++) { console.time('while'); let sum = 0; let i = 0; while (i < len) { sum += arr[i] % 100; i++; } console.timeEnd('while'); } console.log('\ntest do-while'); for (let k = 0; k < 10; k++) { console.time('do-while'); let sum = 0; let i = 0; do { sum += arr[i] % 100; i++; } while (i < len); console.timeEnd('do-while'); }
while 循环和 do-while 循环的结果几乎一样,我们只看下 while 循环在浏览器上运行的结果:
跟 for 循环的速度不相上下。
3. forEach、map 和 reduce 循环接下来来到我们常用的数组三剑客了:forEach, map, reduce 等,这 3 个方法都是在 ES6 标准上新加的语法。
3.1 forEach 的简要介绍
这几种方法是无法停止循环的,无论使用break还是return,都无法停止整个循环。我们可以做一个测试,例如我想当遇到 3 的倍数时,即停止循环
[1, 2, 3, 4, 5].forEach((item) => { console.log(`before return: ${item}`); if (item % 3 === 0) { return; } console.log(`after return: ${item}`); });
运行结果如下:
从运行的结果可以看到,我们的 return 只是没有执行当时循环时后面的语句,但并没有停止整个循环,后面的 4 和 5 依然正常输出。
那循环是否真的像炫迈一样停不下来吗?并不,还有一种方式,可以停止循环。那就是抛出异常:
try { [1, 2, 3, 4, 5].forEach((item) => { console.log(`before return: ${item}`); if (item % 3 === 0) { throw new Error('break forEach'); } console.log(`after return: ${item}`); }); } catch (e) {}
在 forEach 中抛出异常后,就可以停止该循环,然后再使用try-catch捕获异常,避免整个服务被挂掉。
虽然可以停止 forEach 的循环,但实现起来麻烦了不少。因此若没有停止整个循环的需求,可以使用 forEach, map 等循环方式;否则还是要使用其他的循环方式。
3.2 forEach 等的测速
好的,接下来我们就要测试这 3 个循环方式的循环速度了。
// forEach 的测试: console.log('\ntest forEach'); for (let k = 0; k < 10; k++) { console.time('forEach'); let sum = 0; arr.forEach((item) => { sum += item % 100; }); console.timeEnd('forEach'); }
// map 的测试: console.log('\ntest map'); for (let k = 0; k < 10; k++) { console.time('map'); let sum = 0; arr.map((item) => { sum += item % 100; }); console.timeEnd('map'); }
// reduce 的测试: console.log('\ntest reduce'); for (let k = 0; k < 10; k++) { console.time('reduce'); let sum = 0; arr.reduce((_, item) => { sum += item % 100; }, 0); console.timeEnd('reduce'); }
因这 3 个循环的时间差不多,我这里就只截取了 forEach 的测试结果。
执行 10 次循环后,forEach 的执行时间差不多在 10.8ms 左右,比上面的 for 循环和 while 循环高了将近 10 倍的运行时间。
4. for-ofES6 借鉴 C++、Java、C# 和 Python 语言,引入了 for...of 循环,作为遍历所有数据结构的统一的方法。
4.1 for-of 的简要介绍
一个数据结构只要部署了 Symbol.iterator 属性,就被视为具有 iterator 接口,就可以用 for...of 循环遍历它的成员。也就是说,for...of 循环内部调用的是数据结构的 Symbol.iterator 方法。
for...of 循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如 arguments 对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串。
for-of 拿到的就是 value 本身,而 for-in 则拿到的是 key,然后通过 key 再获取到当前数据。
const fruits = ['apple', 'banana', 'orange', 'lemon']; for (const value of fruits) { console.log(value); // 'apple', 'banana', 'orange', 'lemon' }
4.2 for-of 的循环测速
测试 for-of 循环速度的代码:
console.log('\ntest for-of'); for (let k = 0; k < 10; k++) { console.time('for-of'); let sum = 0; for (const value of arr) { sum += value % 100; } console.timeEnd('for-of'); }
测试结果:
在多次重复同一个循环时,前 2 次的 for-of 循环时间会比较长,得在 15ms 以上。但后续的执行,循环速度就下降到 1.5ms 左右了,与 for 循环的时间差不多。
5. for-in 循环for-in 通常用于 object 类型的循环,但也可以用来循环数组,毕竟所有数据类型的祖先都是 object 类型。
console.log('\ntest for-in'); for (let k = 0; k < 10; k++) { console.time('for-in'); let sum = 0; for (let key in arr) { sum += arr[key] % 100; } console.timeEnd('for-in'); }
测试结果:
for-in 循环的测速数据很惊人,简直是独一档的存在了,最好的时候也至少需要 136ms 的时间。可见 for-in 的循环效率真的很低。
数组类型的数据还是不要使用采用 for-in 循环了;Object 类型的可以通过Object.values()先获取到所有的 value 数据,然后再使用 forEach 循环:
const obj = {}; for (let i = 0; i < len; i++) { obj[i] = Math.floor(Math.random() * len); } for (let k = 0; k < 10; k++) { console.time('forEach-values'); let sum = 0; Object.values(obj).forEach((item) => { sum += item % 100; }); console.timeEnd('forEach-values'); }
即使多了一步操作,循环时间也大概在 14ms 左右,要比 for-in 快很多。
6. 总结我们把所有的循环数据放到一起对比一下,我们这里将每个循环的测试次数调整为 100 次,横轴是循环的次数,数轴是循环的时间:
1.for 循环、while 循环和 d-while 循环的时间最少;
2.for-of 循环的时间稍长;
3.forEach 循环、map 循环和 reduce 循环 3 者的数据差不多,但比 for-of 循环的时长更长一点;
4.for-in 循环所需要的时间最多;
每种循环的时长不一样,我们在选择循环方式时,除了考虑时间外,也要考虑到语义化和使用的场景。
以上就是详解JS中你不知道的各种循环测速的详细内容,更多关于JS中各种循环测速的资料请关注开心学习网其它相关文章!
- js中this的用法
- mysqljson字段查询(Mysql 查询JSON结果的相关函数汇总)
- react组件分析(react-diagram 序列化Json解读案例分析)
- jsp实现短信验证码(手动实现js短信验证码输入框)
- php入门教程源代码修改教程(php+js实现的无刷新下载文件功能示例)
- js宏任务都有哪些(JavaScript 操作宏任务与微任务)
- docker node 分阶段构建(Docker安装、创建镜像、加载并运行NodeJS程序的详细过程)
- js事件冒泡与事件捕获(基于事件冒泡、事件捕获和事件委托详解)
- JS中错误处理
- js网页截图(JS如何实现页面截屏功能实例代码)
- js的replace的用法
- tomcat服务如何在eclipse中配置(HBuilderX配置tomcat外部服务器查看编辑jsp界面的方法详解)
- extjs tabPanel的用法
- vue.js 怎么做插件(Vue.js实现音乐播放器)
- js扫雷小游戏源代码(原生js实现简单贪吃蛇小游戏)
- js统计文本框剩余可输入字数
- 冬季养殖这6种阴生植物,方便又好养,你家有么(冬季养殖这6种阴生植物)
- 阴生植物为什么不怕照不到阳光(阴生植物为什么不怕照不到阳光)
- 阴生环境 耐阴地被植物,你知道哪些(阴生环境耐阴地被植物)
- 常见的喜阴植物有哪些 养室内盆栽就在这里选(常见的喜阴植物有哪些)
- 这8种耐阴植物,营造阴生植物花境,也是一个不错的选择(营造阴生植物花境)
- 览邦G08 Plus SMART WATCH 测评⑱ 全独立这才是智能手表该有的样子(览邦G08PlusSMART)
热门推荐
- 时间日期python实例(Python之时间和日期使用小结)
- sqlserver怎么修改表结构(SQL Server中修改“用户自定义表类型”问题的分析与方法)
- docker端口映射怎么添加(Docker 动态修改容器端口映射的方法)
- mysql8.0配置优化参数(MySQL 8.0 新特性之检查约束的实现)
- apache服务器的安全配置(Apache常用虚拟主机配置方法解析)
- html5封闭ios(Html5 页面适配iPhoneX就是那么简单)
- php列表怎么用(PHP开启目录引索+fancyindex漂亮目录浏览带搜索功能)
- 聊天室python小程序(用Python写一个模拟qq聊天小程序的代码实例)
- docker和tomcat建立连接(如何基于Dockerfile构建tomcat镜像)
- 怎么查看mysql计划执行情况(详解 MySQL 执行计划)