JavaScript for 循环

张开发
2026/4/14 23:14:45 15 分钟阅读

分享文章

JavaScript for 循环
JavaScriptfor循环学习笔记循环是编程中最核心的控制结构之一用于重复执行一段代码直到满足特定条件。JavaScript 提供了多种循环方式每种都有其特定的使用场景。1. 标准for循环最经典、最灵活的循环结构适用于已知循环次数或需要精细控制的场景。1.1 语法结构for(初始化表达式;条件表达式;更新表达式){// 循环体要重复执行的代码}执行流程初始化只执行一次通常用于声明计数器。条件判断如果为true执行循环体如果为false跳出循环。执行循环体。更新执行更新表达式通常用于计数器自增/自减。回到步骤 2。1.2 基础示例// 打印 0 到 4for(leti0;i5;i){console.log(i);}// 输出0, 1, 2, 3, 41.3 关键细节letvsvar使用let声明循环变量变量具有块级作用域每次迭代都是独立的解决闭包问题。使用var声明变量具有函数作用域所有迭代共享同一个变量在异步回调中容易出错。// ✅ 推荐 (let)for(leti0;i3;i){setTimeout(()console.log(i),100);}// 输出0, 1, 2 (正确)// ❌ 不推荐 (var)for(varj0;j3;j){setTimeout(()console.log(j),100);}// 输出3, 3, 3 (错误循环结束时 j 为 3)无限循环风险如果条件永远为true且没有break会导致浏览器卡死。// 危险// for (let i 0; ; i) { ... }2.for...of循环 (ES6)推荐用于遍历可迭代对象数组、字符串、Map、Set 等。它直接获取值语法简洁。2.1 语法for(variableofiterable){// 循环体}2.2 示例constfruits[苹果,香蕉,橙子];// 遍历数组值for(constfruitoffruits){console.log(fruit);}// 输出苹果, 香蕉, 橙子// 遍历字符串for(constcharofHello){console.log(char);}// 输出H, e, l, l, o// 遍历 Map (获取 [key, value] 数组)constmapnewMap([[a,1],[b,2]]);for(const[key,value]ofmap){console.log(${key}:${value});}2.3 特点只读值默认获取的是值不是索引。如果需要索引需配合entries()或手动计数。支持break和continue。不能直接遍历普通对象对象不是可迭代对象除非自定义 Symbol.iterator。3.for...in循环专门用于遍历对象的可枚举属性键名。也可以用于数组但不推荐因为会遍历原型链上的属性且顺序不保证。3.1 语法for(variableinobject){// 循环体}3.2 示例constperson{name:Alice,age:25,city:Beijing};// 遍历对象键for(constkeyinperson){console.log(${key}:${person[key]});}// 输出name: Alice, age: 25, city: Beijing// ❌ 不推荐用于数组 (会遍历原型链顺序不确定)constarr[a,b,c];arr.customProptest;// 自定义属性for(constindexinarr){console.log(index);// 输出0, 1, 2, customProp (包含自定义属性)}3.3 注意事项遍历的是键名 (Key)不是值。顺序不保证虽然现代引擎通常按插入顺序遍历但规范未强制。包含原型链如果对象原型上有可枚举属性也会被遍历到。constobj{a:1};Object.prototype.b2;// 污染原型 (不推荐)for(constkeyinobj){console.log(key);// 输出a, b}// 解决方案使用 hasOwnProperty 过滤for(constkeyinobj){if(obj.hasOwnProperty(key)){console.log(key);// 只输出a}}4.while循环当循环次数未知仅依赖条件判断时使用。4.1 语法while(条件表达式){// 循环体// 必须包含更新条件的代码否则死循环}4.2 示例letcount0;while(count5){console.log(count);count;// 必须手动更新}4.3 适用场景等待异步操作完成。读取流数据直到结束。游戏主循环。5.do...while循环至少执行一次循环体然后再判断条件。5.1 语法do{// 循环体}while(条件表达式);5.2 示例letinput;do{inputprompt(请输入密码 (至少6位):);}while(input.length6);console.log(密码有效);特点即使条件一开始就为false循环体也会执行一次。6. 循环控制语句6.1break立即终止整个循环跳出循环体。for(leti0;i10;i){if(i5){break;// 当 i 为 5 时直接跳出}console.log(i);// 输出 0, 1, 2, 3, 4}6.2continue跳过当前迭代直接进入下一次循环执行更新表达式然后判断条件。for(leti0;i5;i){if(i2){continue;// 跳过 i2 的打印}console.log(i);// 输出0, 1, 3, 4}6.3 标签 (Labels)用于控制嵌套循环的跳出。outerLoop:for(leti0;i3;i){for(letj0;j3;j){if(i1j1){breakouterLoop;// 跳出外层循环}console.log(i${i}, j${j});}}// 输出// i0, j0// i0, j1// i0, j2// i1, j0// (i1, j1 时直接跳出不再执行后续)7. 循环性能与最佳实践7.1 性能对比标准for通常性能最好尤其是遍历数组时。for...of性能略低于标准for但代码更简洁现代引擎优化得很好。for...in性能最差严禁用于数组遍历。forEach/map/filter函数式方法代码可读性好但性能略低于for循环因为函数调用开销且无法使用break/continue。7.2 选择指南场景推荐循环理由遍历数组 (需要索引)for或for...ofentries()性能高控制灵活遍历数组 (只需值)for...of语法简洁语义清晰遍历对象属性for...in(配合hasOwnProperty)唯一原生方式遍历 Map/Setfor...of原生支持迭代器未知循环次数while/do...while依赖条件判断需要中断循环for/while/for...of支持break函数式编程风格forEach/map/filter链式调用无副作用7.3 常见陷阱修改数组长度在for循环中修改数组长度如push/pop可能导致跳过元素或死循环。constarr[1,2,3];for(leti0;iarr.length;i){if(arr[i]2){arr.push(4);// 修改长度}}// 可能导致无限循环或逻辑错误解决缓存长度const len arr.length或使用for...of。异步循环在循环中使用async/await时for...of会等待每个迭代完成而forEach不会。// ✅ 正确等待每个请求完成for(consturlofurls){awaitfetch(url);}// ❌ 错误所有请求同时发起无法控制顺序urls.forEach(async(url){awaitfetch(url);});for...in遍历数组顺序不保证。会遍历原型链属性。索引是字符串类型。永远不要用for...in遍历数组8. 实战示例示例 1查找数组中的元素functionfindIndex(arr,target){for(leti0;iarr.length;i){if(arr[i]target){returni;}}return-1;}示例 2累加数组元素constnumbers[1,2,3,4,5];letsum0;// 使用 for...offor(constnumofnumbers){sumnum;}console.log(sum);// 15示例 3对象属性过滤constusers[{name:Alice,age:25,active:true},{name:Bob,age:30,active:false},{name:Charlie,age:22,active:true}];// 找出所有活跃用户constactiveUsers[];for(constuserofusers){if(user.active){activeUsers.push(user);}}示例 4嵌套循环 (打印乘法表)for(leti1;i9;i){letrow;for(letj1;ji;j){row${j}x${i}${i*j}\t;}console.log(row);}9. 总结速查表循环类型适用场景优点缺点for需要索引、精细控制、性能敏感灵活、性能高语法稍繁琐for...of遍历数组、字符串、Map、Set语法简洁、语义清晰无法直接获取索引 (需配合entries)for...in遍历对象键唯一遍历对象方式顺序不定、包含原型链、不可用于数组while未知次数、条件驱动灵活容易忘记更新条件导致死循环do...while至少执行一次保证执行一次语法稍特殊forEach函数式风格、无中断需求代码简洁、链式调用无法break/continue、性能略低核心建议遍历数组优先用for...of(只需值) 或for(需索引)。遍历对象用for...in(配合hasOwnProperty) 或Object.keys()。避免在循环中修改被遍历的数组长度。异步操作使用for...ofawait。始终使用let声明循环变量。掌握这些循环方式你就能应对 JavaScript 中绝大多数重复性任务

更多文章