核心是将O(n²)降为O(n),关键在于用哈希表建索引替代内层遍历、缓存不变量(如length、DOM属性)、选用可中断的原生方法(some/findIndex)、提取复用逻辑并避免闭包捕获冗余数据。

核心思路是把 O(n²) 降为 O(n),关键不在“写得更短”,而在“让引擎少做重复事、少走弯路”。
用哈希表替代内层遍历
当嵌套循环本质是在找“匹配项”(比如按 id 关联两个数组),直接用对象或 Map 建索引,把查找从线性扫描变成常数时间。
- 反例:双重 for 查找匹配
- 正例:先遍历 arr2 构建 id → item 映射,再单层遍历 arr1 查表赋值
- 效果:1000 × 1000 次操作 → 2000 次操作,性能差距可达百倍
提前缓存不变量和深层属性
循环体内每次访问 obj.data.items.length 或 array.length,V8 都要重新查属性链或读取长度——哪怕值根本没变。
- 把
const len = arr.length、const items = obj.data.items提到循环外 - DOM 属性如
el.offsetTop同理,缓存后避免强制重排(layout thrashing) - 对高频调用的函数结果也可 memoize,但需权衡内存开销
用语义清晰且可控的替代方案
不是所有场景都适合硬拆嵌套,有时换一种结构更自然也更高效。
立即学习“Java免费学习笔记(深入)”;
- 用
for而非forEach或for...of:前者支持break/continue,可提前退出 - 避免链式调用如
arr.filter(...).find(...):它会新建中间数组,而实际只需一个匹配项 - 条件允许时,改用
some()、findIndex()等原生中断型方法
把逻辑拆出函数并复用计算结果
嵌套里重复执行相同逻辑(比如格式化、校验、拼接),不仅拖慢速度,还掩盖真实瓶颈。
- 把循环体中稳定的部分提取成独立函数,便于测试和复用
- 若多个循环共用同一组预处理数据(如排序后数组、归一化后的坐标),只算一次,传参复用
- 警惕闭包捕获整个大对象——只传真正需要的字段,减少 GC 压力


















