了解哪一种 for 循环或迭代器适合我们的需求,防止我们犯下一些影响应用性能的低级错误。

JavaScript 是 Web 开发领域的“常青树”。无论是 JavaScript 框架(如 Node.js、React、Angular、Vue 等),还是原生 JavaScript,都拥有非常庞大的粉丝基础。我们来谈谈现代 JavaScript 吧。循环一直是大多数编程语言的重要组成部分,而现代 JavaScript 为我们提供了许多迭代或循环值的方法。
但问题在于,我们是否真的知道哪种循环或迭代最适合我们的需求。for 循环有很多变形,例如 for、for(倒序)、for…of、forEach、for…in、for…await。本文将围绕这些展开讨论。

究竟哪一种循环更快?

答案其实是: for(倒序)

最让我感到惊讶的事情是,当我在本地计算机上进行测试之后,我不得不接受 for(倒序)是所有 for 循环中最快的这一事实。下面我会举个对一个包含超过一百万项元素的数组执行一次循环遍历的例子。
声明:console.time() 结果的准确度在很大程度上取决于我们运行测试的系统配置。你可以在此处对准确度作进一步了解。

const million = 1000000; 
const arr = Array(million);

// 注:这是稀疏数组,应该为其指定内容,否则不同方式的循环对其的处理方式会不同:
// const arr = [...Array(million)]

console.time('?');
for (let i = arr.length; i > 0; i--) {} // for(倒序) :- 1.5ms
for (let i = 0; i < arr.length; i++) {} // for     :- 1.6ms
arr.forEach(v => v)           // foreach   :- 2.1ms
for (const v of arr) {}         // for...of   :- 11.7ms
console.timeEnd('?');

造成这样结果的原因很简单,在代码中,正序和倒序的 for 循环几乎花费一样的时间,仅仅相差了 0.1 毫秒。原因是,for(倒序)只需要计算一次起始变量 let i = arr.length,而在正序的 for 循环中,它在每次变量增加后都会检查条件 i<arr.length。这个细微的差别不是很重要,你可以忽略它。(译者注:在数据量小或对时间不敏感的代码上,我们大可忽略它,但是根据译者的测试,当数据量扩大,例如十亿,千亿等的数量级,差距就显著提升,我们就需要考虑时间对应用程序性能的影响了。)
而 forEach 是 Array 原型的一个方法,与普通的 for 循环相比,forEach 和 for…of 需要花费更多的时间进行数组迭代。(译者注:但值得注意的是,for…of 和 forEach 都从对象中获取了数据,而原型并没有,因此没有可比性。)

循环的类型,以及我们应该在何处使用它们

1. For 循环(正序和倒序)

我想,也许大家都应该对这个基础循环非常熟悉了。我们可以在任何我们需要的地方使用 for 循环,按照核定的次数运行一段代码。最基础的 for 循环运行最迅速的,那我们每一次都应该使用它,对吗?并不然,性能不仅仅只是唯一尺度,代码可读性往往更加重要,就让我们选择适合我们应用程序的变形即可。

2. forEach

这个方法需要接受一个回调函数作为输入参数,遍历数组的每一个元素,并执行我们的回调函数(以元素本身和它的索引(可选参数)作为参数赋予给回调函数)。forEach 还允许在回调函数中使用一个可选参数 this。

const things = ['have', 'fun', 'coding'];
const callbackFun = (item, idex) => {
  console.log(`${item} - ${index}`);
}
things.foreach(callbackFun); 
/* 输出  have - 0
    fun - 1
    coding - 2 */

需要注意的是,如果我们要使用 forEach,我们不能使用 JavaScript 的短路运算符,即不能在每一次循环中跳过或结束循环。

3. for…of

for…of 是在 ES6(ECMAScript 6)中实现标准化的。它会对一个可迭代的对象(例如 array、map、set、string 等)创建一个循环,并且有一个突出的优点,即优秀的可读性。

const arr = [3, 5, 7];
const str = 'hello';
for (let i of arr) {
  console.log(i); // 输出 3, 5, 7
}
for (let i of str) {
  console.log(i); // 输出 'h', 'e', 'l', 'l', 'o'
}

需要注意的是,请不要在生成器中使用 for……of,即便 for……of 循环提前终止。在退出循环后,生成器被关闭,并尝试再次迭代,不会产生任何进一步的结果。

4. for in

for…in 会在对象的所有可枚举属性上迭代指定的变量。对于每个不同的属性,for…in 语句除返回数字索引外,还将返回用户定义的属性的名称。

因此,在遍历数组时最好使用带有数字索引的传统 for 循环。 因为 for…in 语句还会迭代除数组元素之外的用户定义属性,就算我们修改了数组对象(例如添加自定义属性或方法),依然如此。

const details = {firstName: 'john', lastName: 'Doe'};
let fullName = '';
for (let i in details) {
  fullName += details[i] + ' '; // fullName: john doe
}

for…of 和 for…in

for…of 和 for…in 之间的主要区别是它们迭代的内容。for…in 循环遍历对象的属性,而 for…of 循环遍历可迭代对象的值。

let arr= [4, 5, 6];
for (let i in arr) {
  console.log(i); // '0', '1', '2'
}
for (let i of arr) {
  console.log(i); // '4', '5', '6'
}

结论

  • for 最快,但可读性比较差
  • foreach 比较快,能够控制内容
  • for...of 比较慢,但香
  • for...in 比较慢,没那么方便

最后,给你一条明智的建议 —— 优先考虑可读性。尤其是当我们开发复杂的结构程序时,更需要这样做。当然,我们也应该专注于性能。尽量避免增添不必要的、多余的花哨代码,因为这有时可能对你的程序性能造成严重影响。祝你编码愉快。

译者注

在译者的实际测试中,发现:

  • 不同浏览器甚至不同版本,结果会有不一样(颠倒,例如 Firefox 对原生 for-loop 似乎不太友好,Safari 极度喜欢 while)
  • 不同平台操作系统处理器,结果会有不一样

到此这篇关于详解JavaScript中哪一种循环最快呢的文章就介绍到这了,更多相关JavaScript哪一种循环最内容请搜索乐虎体育以前的文章或继续浏览下面的相关文章希望大家以后多多支持乐虎体育!

原文地址:Which type of loop is fastest in JavaScript?
原文作者:kushsavani

详解JavaScript中哪一种循环最快呢的更多相关文章

  1. js加减乘除精确运算方法实例代码

    前言因为计算机数字是浮点型,所以在计算过程中通常得到的并不是一个准确的数据,所以在做一些数组运算的时候比较头疼,我们......

  2. JavaScript实现浏览器网页自动滚动并点击的示例代码

    1. 打开浏览器控制台窗口JavaScript通常是作为开发Web页面的脚本语言,本文介绍的JavaScript代码......

  3. javascript中call,apply,bind的区别详解

    在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢。在说区别之前还是先总结一下三者的相似之......

  4. JS中循环遍历数组的四种方式总结

    本文比较并总结遍历数组的四种方式:for 循环:for (let index=0; index < someA......

  5. JavaScript如何操作css

    原本应该是由css进行控制html中的div的宽高和背景颜色,但是在下方使用了JavaScript进行重新调用了di......

  6. 【机制】js的闭包、执行上下文、作用域链

    1.从闭包说起什么是闭包一个函数和对其周围状态(词法环境)的引用捆绑在一起,这样的组合就是闭包。也就是说,闭包让你可......

  7. JavaScript/TypeScript 实现并发请求控制的示例代码

    场景假设有 10 个请求,但是最大的并发数目是 5 个,并且要求拿到请求结果,这样就是一个简单的并发请求控制模拟利用......

  8. javascript 箭头函数的使用介绍

    本文介绍箭头(arrow)函数的优点,更简洁的语法我们先来按常规语法定义函数:function funcName......

  9. 在JavaScript中查找字符串中最长单词的三种方法(推荐)

    本文基于Free Code Camp基本算法脚本“查找字符串中最长的单词”。在此算法中,我们要查看每个单词并计算每个......

  10. JavaScript中是如何定义私有变量的

    JavaScript并不像别的语言,能使用关键字来声明私有变量。我了解的JavaScript能用来声明私有变量的方式......

随机推荐

  1. Python监控进程状态并实现告警

    公司的应用程序有时候会莫名其妙地挂掉,如果我们经常去登录服务器看是不是程序挂了,挂了再拉起,那样是非常耗时和麻烦的事......

  2. ASP.NET Core 5.0 MVC中的 Razor 页面 介绍

    Razor 是一个用于将基于服务器的代码嵌入到网页中的标记语法。 Razor语法由 Razor 标记、c # 和 H......

  3. Ajax实现局部刷新的方法实例

    前言 最近复习了一下jQuery的一些内容,特此整理一下一些能用的得到的知识点,以前才学jQuery的时候压根就没有......

  4. java中DelayQueue实例用法详解

    在阻塞队里中,除了对元素进行增加和删除外,我们可以把元素的删除做一个延迟的处理,即使用DelayQueue的方法。这......

  5. 用python制作个音乐下载器

    前言某个夜深人静的夜晚,我打开了自己的文件夹,发现了自己写了许多似乎很无聊的代码。于是乎,一个想法油然而生:“生活已......

  6. 阿里面试:MySQL如何设计索引更高效?

    前言数据库系列更新到现在我想大家对所有的概念都已有个大概认识了,这周我在看评论的时候我发现有个网友的提问我觉得很有意......

  7. Perl字符串处理函数大全

    下面请看本文详细介绍.Perl字符串处理函数1. index语法:position=index(string,sub......

  8. 如何通过SQL注入盗取数据库信息

    目录数据库结构注入示例判断共有多少字段判断字段的显示位置显示登录用户和数据库名查看所有数据库名查看数据库的所有表名查......

  9. C# 忽略大小写进行字符串比较

    使用场景字符串比较在EF或者其他地方使用的时候,字符串的比较非常常见。使用全部转化为大写或者小写进行比较,有时候并不......

  10. Java中ArrayList集合的常用方法大全

    ArrayList集合的创建非泛型创建ArrayList集合对象,可以添加任意Object子类元素至集合//非泛型创......