news 2026/5/26 3:27:49

JavaScript中的循环特点和区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript中的循环特点和区别

一、前言:循环在 JS 中的核心地位

循环是编程的基础逻辑之一,在 JavaScript 中更是贯穿前端开发、Node.js 后端等所有场景 —— 从 DOM 遍历、数据处理到异步流程控制,几乎无处不在。但多数开发者仅停留在for/forEach的基础使用,忽略了不同循环的适用场景、性能差异和进阶技巧。本文将从基础语法到实战优化,全面拆解 JS 循环的核心知识点,帮你掌握 “什么时候用什么循环” 的底层逻辑。

二、JS 循环的 5 大核心类型:语法与基础用法

1. 传统循环:for/while/do...while

这是最基础的循环类型,兼容性覆盖所有浏览器(包括 IE),核心优势是完全可控(可中断、可跳过、可反向遍历)。

  • for循环:适合已知遍历次数的场景

// 正向遍历数组

const arr = [1, 2, 3, 4];

for (let i = 0; i < arr.length; i++) {

console.log(arr[i]); // 1,2,3,4

}

// 反向遍历(性能更优,减少数组长度读取)

for (let i = arr.length - 1; i >= 0; i--) {

console.log(arr[i]); // 4,3,2,1

}

  • while循环:适合未知遍历次数的场景(需手动控制终止条件)

let count = 0;

while (count ) {

console.log(count); // 0,1,2

count++;

}

  • do...while循环:与while的区别是至少执行一次

let count = 3;

do {

console.log(count); // 3(即使条件不满足,仍执行一次)

count++;

} while (count );

2. 数组专用循环:forEach

ES5 引入的数组遍历方法,语法简洁,无需手动控制索引,但无法中断循环(break/return无效,return仅相当于跳过当前迭代)。

const arr = [1, 2, 3];

arr.forEach((item, index, array) => {

if (item === 2) return; // 跳过当前项,继续执行下一次

console.log(item); // 1,3

});

⚠️ 注意:forEach遍历稀疏数组时,会跳过空元素(与for循环不同)。

3. 迭代器循环:for...in/for...of

ES6 引入的新型循环,基于迭代器(Iterator)协议,适用于不同数据结构的遍历。

  • for...in:遍历对象的可枚举属性(包括原型链上的属性),不建议用于数组(会遍历数组的索引及自定义属性)。

const obj = { name: "张三", age: 20 };

for (const key in obj) {

// 过滤原型链属性

if (obj.hasOwnProperty(key)) {

console.log(`${key}: ${obj[key]}`); // name: 张三, age: 20

}

}

  • for...of:遍历可迭代对象(数组、字符串、Map、Set 等)的,支持break/continue/return中断循环,是数组遍历的优选方案。

// 遍历数组

const arr = [1, 2, 3];

for (const item of arr) {

if (item === 2) break; // 中断循环

console.log(item); // 1

}

// 遍历Map

const map = new Map([["name", "张三"], ["age", 20]]);

for (const [key, value] of map) {

console.log(`${key}: ${value}`); // name: 张三, age: 20

}

三、关键对比:不同循环的适用场景与性能

1. 功能对比表

循环类型

适用场景

能否中断

遍历空元素

遍历原型属性

for

数组、已知次数的遍历

-

while/do...while

未知次数的遍历

-

-

forEach

数组遍历(无需中断)

-

for...in

对象属性遍历

-

是(需过滤)

for...of

可迭代对象的值遍历

否(数组)

-

2. 性能分析(基于 Chrome 浏览器测试)
  • 性能排序(从快到慢):for(反向)> for(正向)> for...of > forEach > for...in
  • 核心原因:
    • for循环无额外函数调用和迭代器开销,直接操作索引,性能最优;
    • for...of基于迭代器,但底层优化较好,性能接近for;
    • forEach每次迭代需调用回调函数,存在函数调用开销;
    • for...in需遍历原型链属性,且需判断属性是否为自身所有,性能最差。

⚠️ 注意:性能差异仅在大数据量(10 万 + 条数据)下明显,日常开发中优先考虑代码可读性,无需过度优化。

四、进阶技巧:循环的高级用法与避坑指南

1. 中断循环的正确方式
  • 可中断循环:for/while/do...while/for...of(用break中断,continue跳过当前迭代);
  • 不可中断循环:forEach(需中断时,建议替换为for...of或for循环);
  • 替代方案:数组方法some/every(本质是遍历,但可通过return true中断):

const arr = [1, 2, 3];

// some:找到满足条件的项后中断,返回true

arr.some(item => {

if (item === 2) return true;

console.log(item); // 1

});

2. 异步循环的坑与解决方案

问题:forEach/for...in中使用异步操作(如setTimeout、接口请求)时,循环会先执行完,异步回调才触发,导致索引 / 值错乱。

// 错误示例:所有回调都打印4(i最终为4)

const arr = [1, 2, 3];

for (var i = 0; i < arr.length; i++) {

setTimeout(() => console.log(arr[i]), 0);

}

解决方案

  • 用let声明索引(块级作用域,每次迭代创建独立变量);
  • 用for...of(天然支持异步中断);
  • 用Promise.all(并行执行异步操作)。

// 正确示例:用for...of

const arr = [1, 2, 3];

async function asyncLoop() {

for (const item of arr) {

await new Promise(resolve => setTimeout(() => {

console.log(item); // 1,2,3(顺序执行)

resolve();

}, 1000));

}

}

asyncLoop();

3. 循环优化技巧
  • 数组遍历前缓存长度:`for (let i = 0, len = arr.length; i (避免每次迭代读取数组长度);
  • 反向遍历数组:减少数组索引边界判断(i >= 0比 `i 简单);
  • 大数据量遍历用for或for...of,避免forEach和for...in;
  • 遍历对象属性时,用Object.keys(obj).forEach替代for...in(避免原型链问题)。

五、实战场景:循环的最佳实践

  1. 场景 1:数组遍历并中断→ 用for...of或for循环;
  1. 场景 2:数组遍历无需中断,追求简洁→ 用forEach;
  1. 场景 3:对象属性遍历→ 用Object.keys(obj).forEach或for...in(需过滤原型链);
  1. 场景 4:Map/Set 遍历→ 用for...of;
  1. 场景 5:异步遍历(顺序执行)→ 用for...of+async/await;
  1. 场景 6:异步遍历(并行执行)→ 用Promise.all(arr.map(async item => {}))。

六、总结

JavaScript 循环的核心是 “选择合适的工具解决对应问题”:基础场景用for/forEach,对象遍历用Object.keys+forEach,可迭代对象用for...of,异步场景用for...of+async/await。掌握不同循环的语法、性能和适用场景,不仅能提升代码可读性,还能在大数据量场景下优化性能。

记住:没有最好的循环,只有最适合的循环。在实际开发中,需结合业务场景、代码可读性和性能需求综合选择。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 19:33:48

PyULog:无人机飞行日志数据解析与分析的完整解决方案

PyULog&#xff1a;无人机飞行日志数据解析与分析的完整解决方案 【免费下载链接】pyulog Python module & scripts for ULog files 项目地址: https://gitcode.com/gh_mirrors/py/pyulog 你是否曾面对PX4无人机生成的二进制ULog文件感到无从下手&#xff1f;那些记…

作者头像 李华
网站建设 2026/5/25 17:44:13

Linux上IO性能问题的故障排除实践

文章目录引言详解Linux系统IO性能问题排查通用步骤1. 检查服务器负载2. 查看IO使用率3. 明确定位IO进程其他有用的IO分析工具小结参考引言 在监控工具盛行的今天&#xff0c;学会传统的系统性能瓶颈排查手段也是必要的技术储备&#xff0c;它可以让你保持对系统指标的敏感度&a…

作者头像 李华
网站建设 2026/5/25 18:57:01

抖音批量下载终极指南:开源工具高效使用手册

抖音批量下载终极指南&#xff1a;开源工具高效使用手册 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 还在为保存喜欢的抖音视频而烦恼吗&#xff1f;手动下载、去水印、整理文件&#xff0c;这些重复性工…

作者头像 李华
网站建设 2026/5/26 7:15:28

Wan2.2-T2V-A14B模型生成视频的元数据嵌入与追踪

Wan2.2-T2V-A14B模型生成视频的元数据嵌入与追踪 在AI生成内容&#xff08;AIGC&#xff09;飞速普及的今天&#xff0c;一段由“宇航员漫步火星”这样一句话生成的高清视频&#xff0c;可能只需几十秒就能完成。但随之而来的问题也愈发尖锐&#xff1a;这段视频是谁生成的&…

作者头像 李华
网站建设 2026/5/26 6:54:26

Mendeley文献管理 数量太多更新太慢

最后一次更新时可以新建一个文档&#xff0c;把参考文献很多的那部分一点一点的复制到新文档中&#xff0c;这样每一部分就可以很快的更新完成。

作者头像 李华