ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

30 seconds of code:需要提前跳出循环时,为什么 for 循环比数组方法更合适

30 seconds of code:需要提前跳出循环时,为什么 for 循环比数组方法更合适 教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载在 JavaScript 中遍历数组的方式非常多Array.prototype.forEach()、map()、filter()等数组方法凭借其函数式风格深受欢迎但它们在需要提前跳出循环的场景下存在天然短板。本篇指南以 30 seconds of code 仓库中的 for-loop-early-break 文档为核心深入讲解for循环在提前退出场景下的性能优势、与for...in/for...of/forEach()的语义差异并结合仓库内真实代码用例帮助你在正确的场景选择正确的迭代方式。为什么现代 JavaScript 还需要 for 循环数组方法是现代 JavaScript 的主力迭代工具它们让代码更简洁、更声明式。但for循环在两类场景中仍然不可替代需要提前跳出循环数组方法无法真正中断遍历for循环可以配合break或提前return在满足条件时立即停止异步操作串行执行for/for...of循环内配合await可以按顺序逐个等待异步任务完成而数组方法往往做不到这一点详见仓库中的 async-array-loops 文档。换句话说循环 提前退出这类控制流需求恰恰是for循环的用武之地。核心问题forEach() 无法提前跳出循环原文档用一个非常直观的数组比较函数来演示这个问题。先看forEach()版本const smallArray [0, 2]; const largeArray Array.from({ length: 1000 }, (_, i) i); const areEqual (a, b) { let result true; a.forEach((x, i) { if (!result) return; if (b[i] undefined || x ! b[i]) result false; }); return result; } areEqual(largeArray, smallArray); // false // 会遍历 largeArray 中的全部 1000 个元素这段代码虽然能得出正确结果但存在明显的性能隐患Array.prototype.forEach()的回调内return只是结束当前一次回调调用并不会中断整个循环。当largeArray与smallArray在第 2 个元素处就发生不匹配时forEach()仍会继续遍历完剩余的 998 个元素。这正是forEach()的语义限制它对每个元素调用回调却没有任何机制让调用方通知它提前终止。类似的限制同样存在于map()、filter()等绝大多数数组方法中。用 for 循环 提前 return 解决问题针对上述问题原文档给出了基于for循环的优化版本const smallArray [0, 2]; const largeArray Array.from({ length: 1000 }, (_, i) i); const areEqual (a, b) { for (let i in a) { if (b[i] undefined || a[i] ! b[i]) return false; } return true; } areEqual(largeArray, smallArray); // false // 只遍历到第一个不匹配的元素就提前返回两个版本的核心差异一目了然forEach()版本无论是否发现不匹配都会遍历全部 1000 个元素而for循环版本一旦在第 2 个元素发现差异立即return false循环体整体跳出剩余元素不再访问。对于提前终止敏感的算法如查找、校验、比较这种差距会随数组规模线性放大。关于 for...in 的语义提醒原文档示例使用了for (let i in a)需要留意for...in遍历的是对象的可枚举属性对数组而言即索引它会包含继承的可枚举属性通常并不推荐用于数组遍历。仓库中另一篇 for-in-for-of-foreach 文档对此有系统梳理for...in遍历所有可枚举属性数组索引、字符串下标、对象属性名不能用于Map/Setfor...of遍历可迭代对象数组、字符串、Map、Set的值不能直接用于普通对象Array.prototype.forEach()只能遍历数组可同时拿到值与索引。如果你希望按值遍历并配合索引做比较更稳妥的写法通常是for (let i 0; i a.length; i) { if (b[i] undefined || a[i] ! b[i]) return false; }或者用for...of配合entries()拿到索引。for计数器循环的好处是索引语义完全显式、无歧义也最容易让读者理解提前返回的意图。提前退出的其他内置方案短路型数组方法除了for循环标准库其实还提供了一批**天生支持短路提前终止**的数组方法它们在某些场景下比for循环更简洁Array.prototype.some()回调返回真值时立即停止并返回trueArray.prototype.every()回调返回假值时立即停止并返回falseArray.prototype.find()/findIndex()找到第一个匹配项后立即停止。例如上面的数组比较可以改写成const areEqual (a, b) { if (a.length ! b.length) return false; return a.every((x, i) b[i] ! undefined x b[i]); }every()在第一个不匹配元素处就会短路返回false效果与for循环 提前return一致且代码更声明式。仓库中的 array-comparison 文档对比较两个数组的各种方案、JSON.stringify()、every()等有更完整的讨论其中JSON.stringify()方案在边界值如new String(a)与a、null与undefined上会误判可作对照阅读。选择建议逻辑简单、可映射为全满足 / 存在满足的提前退出场景优先用some()/every()/find()需要精细控制索引、需要中途执行多条语句或修改外部状态时for循环更直白。仓库实战sudoku-validator 中 for 循环的提前退出优化for循环 提前退出不是纸上谈兵仓库内的 sudoku-validator 文档就是一个完整的实战案例。该文实现数独校验器时先写了基于filter()Set的版本——先构造出整行/整列/整个 3×3 宫格的值数组再检查是否有重复必须处理完整个区域才能得出结果。随后作者将校验逻辑改写为双重for循环配合Set在遍历过程中即时查重// 行检查节选 for (let i 0; i 9; i) { let uniqueFilled new Set(); for (let j 0; j 9; j) { const cell board[i][j]; if (cell ! .) { if (uniqueFilled.has(cell)) return false; // 发现重复立即跳出 uniqueFilled.add(cell); } } }一旦发现重复数字函数立即return false不再继续扫描剩余单元格。文档作者给出了三个版本的实测对照实现运行时间 (ms)内存 (MB)原始版先构造数组再查重1360.08去掉中间数组版659.94提前返回版for 循环 Set256.99数据来源于仓库文档作者的实际运行结果具体数值会随运行环境变化。同一逻辑仅因能否提前跳出就从 13ms 降到 2ms充分印证了提前退出对性能的直接收益。延伸异步场景下 for 循环的串行能力原文档开头提到for循环在异步操作场景中同样重要仓库的 async-array-loops 文档对此展开了说明for/for...of循环内await会使任务逐个串行执行顺序可控、结果可预期Promise.all()适合需要并行执行的任务但执行顺序不可控Array.prototype.forEach()配合async回调不会等待异步操作完成await形同虚设是常见的隐患写法。结合本篇主题可以这样理解for循环不仅提供提前退出这一控制流能力也提供暂停等待的时序控制能力两者都是数组方法难以直接替代的。总结什么时候该用 for 循环场景推荐做法找到结果后立即停止比较、校验、查找for循环 break/ 提前return或some()/every()/find()需要按索引精细控制遍历过程for计数器循环异步任务需要串行且按序完成for...ofawait只需对每个元素执行副作用、无需提前退出Array.prototype.forEach()任务相互独立、需要并行执行Promise.all()map()for循环虽然不够函数式但在提前退出与异步串行这两类控制流需求面前它依然是 JavaScript 中最可靠、最高效的工具之一。建议进一步阅读仓库中的 for-in-for-of-foreach三种迭代方式语义对比、array-comparison数组比较方案对比与 async-array-loops异步循环三篇相关文档构建完整的迭代选型知识体系。赞分享教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载相关推荐30-seconds-of-code重构 for...in 循环以消除 ESLint 警告的三种方案30 seconds of code重构 for...in 循环以消除 ESLint 警告的三种方案 ESLint 是 JavaScript 开发中最常用的静教程文档30 seconds of codeJavaScript 异步数组循环的三种方案与避坑指南30 seconds of codeJavaScript 异步数组循环的三种方案与避坑指南 异步操作与数组循环的组合是 JavaScript 开发中最容易踩坑教程文档macroquad异步编程详解为什么游戏主循环需要async/awaitmacroquad异步编程详解为什么游戏主循环需要async/await 在现代游戏开发中异步编程已成为提升性能和用户体验的关键技术。macroquad作为游戏开发图形学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表