⚡ 编程实验室🏗️ HTML🎨 CSS⚡ JavaScript🐍 Python🗄️ SQL☕ Java⚛️ React💚 Vue🟢 Node.js⚙️ C语言🐘 PHP🐹 Go🔷 TypeScript🐬 MySQL🔧 C++🎯 C#🦀 Rust🅱️ Bootstrap💡 jQuery🎸 Django🍃 MongoDB👗 Sass🎪 Kotlin📊 R语言📋 XML📊 Excel🐘 PostgreSQL🐳 Docker🅰️ Angular🎮 游戏🏠 网站首页

JS For 循环详解

学习 for/in、for/of 的区别 · 难度:入门 · +10XP

JavaScript For 循环完全指南

循环是编程中最基本的控制结构之一,用于重复执行代码块。JavaScript 提供了多种循环方式:经典的 for 循环、whiledo...while 循环,以及 ES6 引入的 for...of(遍历可迭代对象)和 for...in(遍历对象属性)。选择合适的循环方式能让代码更简洁、更少出错、更易维护。

一、经典 for 循环 —— 精确控制索引

最基础也最灵活的循环形式,由三个部分(初始化、条件判断、每次迭代后执行)组成。适用于明确知道循环次数或需要精确控制索引值的场景。三部分都可以省略,但分号不能省。

// 语法结构:for (初始化; 条件; 每次迭代后执行)
for (let i = 0; i < 5; i++) {
  console.log(第 ${i + 1} 次循环);
}
// 输出: 第1次 ~ 第5次

// 遍历数组(正向) let fruits = ['苹果', '香蕉', '橙子', '葡萄', '西瓜']; for (let i = 0; i < fruits.length; i++) { console.log(水果${i + 1}: ${fruits[i]}); }

// 倒序遍历数组 for (let i = fruits.length - 1; i >= 0; i--) { console.log(倒序: ${fruits[i]}); }

// 步长不为1的循环(只打印偶数索引) for (let i = 0; i < fruits.length; i += 2) { console.log(fruits[i]); // 苹果、橙子、西瓜 }

// 嵌套循环 —— 经典九九乘法表 for (let i = 1; i <= 9; i++) { let row = ''; for (let j = 1; j <= i; j++) { row += ${j}×${i}=${i * j} ; } console.log(row); }

二、while 和 do...while —— 条件驱动的循环

当不确定循环次数、只知循环终止条件时,while 系列循环更合适。while 先判断条件再执行(可能一次都不执行),do...while 先执行一次再判断条件(至少执行一次)。

// while —— 先判断后执行(可能零次)
let count = 0;
while (count < 3) {
  console.log(计数: ${count});
  count++;
}

// do...while —— 先执行后判断(至少一次) let num; let attempts = 0; do { num = Math.floor(Math.random() * 10); attempts++; console.log(第${attempts}次:抽到了 ${num}); } while (num !== 7); console.log(恭喜!经过${attempts}次终于抽到了幸运数字7!);

// while 用于处理未知长度的数据 function countdown(n) { while (n > 0) { console.log(n); n--; } console.log('发射!'); } countdown(5); // 5, 4, 3, 2, 1, 发射!

// 危险:死循环!(不要运行这段代码) // while (true) { console.log('永远循环'); }

三、for...of —— 遍历可迭代对象(强烈推荐)

ES6 引入的 for...of 是遍历数组、字符串、Set、Map、NodeList 等可迭代对象的最佳选择。语法简洁,不需要手动管理索引,也不像 for...in 那样会遍历到原型链上的属性。

// 遍历数组(最常用)
let colors = ['红', '橙', '黄', '绿', '青', '蓝', '紫'];
for (let color of colors) {
  console.log(color);
}

// 遍历字符串(逐字符) for (let char of 'JavaScript') { console.log(char); } // 输出: J, a, v, a, S, c, r, i, p, t

// 遍历 Set(自动去重的集合) let unique = new Set([1, 2, 2, 3, 3, 3, 4]); for (let val of unique) { console.log(val); // 1, 2, 3, 4 }

// 遍历 Map(键值对),用解构赋值同时获取键和值 let map = new Map([ ['name', 'Alice'], ['age', 25], ['city', '北京'] ]); for (let [key, value] of map) { console.log(${key}: ${value}); }

// 如果你需要索引,用 entries() for (let [index, color] of colors.entries()) { console.log(第${index}个颜色: ${color}); }

四、for...in —— 遍历对象属性(谨慎使用)

for...in 用于遍历对象的可枚举属性键名。注意它会沿原型链向上查找,所以通常需要配合 hasOwnProperty() 过滤。对于数组,不推荐使用 for...in(它遍历的是键名字符串而非值,还会包含自定义属性)。

let person = { name: '小明', age: 20, city: '南宁', hobby: '编程' };

// for...in 遍历对象 for (let key in person) { console.log(${key} = ${person[key]}); }

// 安全遍历 —— 过滤掉原型链上的属性 for (let key in person) { if (person.hasOwnProperty(key)) { console.log(自己的属性: ${key}); } }

// 更推荐的方式:Object.keys() + for...of for (let key of Object.keys(person)) { console.log(${key}: ${person[key]}); }

// 同时获取键和值:Object.entries() for (let [key, value] of Object.entries(person)) { console.log(${key} => ${value}); }

// 错误的数组用法(不要这样用!) let arr = ['a', 'b', 'c']; arr.customProp = 'hello'; for (let key in arr) { console.log(key); // "0", "1", "2", "customProp" —— 多出了customProp! } // 正确做法:用 for...of 或 forEach 遍历数组

五、循环控制关键字:break 与 continue

关键字作用影响范围典型场景
break立即终止整个循环跳出当前循环体找到目标后停止搜索
continue跳过本次迭代剩余代码进入下一次迭代跳过不符合条件的元素
// break —— 找到即停止
let numbers = [4, 8, 12, 7, 15, 3, 19];
for (let n of numbers) {
  if (n === 7) {
    console.log(找到了7!索引: ${numbers.indexOf(7)});
    break; // 找到后立即停止,不再检查后面的元素
  }
  console.log(检查了: ${n});
}
// 输出: 检查了:4, 检查了:8, 检查了:12, 找到了7!...

// continue —— 跳过特定元素 for (let i = 1; i <= 10; i++) { if (i % 2 === 0) continue; // 跳过所有偶数 console.log(i); // 只打印奇数: 1, 3, 5, 7, 9 }

// 带标签的 break —— 跳出嵌套循环 outerLoop: for (let i = 1; i <= 3; i++) { for (let j = 1; j <= 3; j++) { if (i === 2 && j === 2) { break outerLoop; // 直接跳出外层循环 } console.log(i=${i}, j=${j}); } }

六、循环方式全面对比

循环类型适用场景优点缺点
for (;;)需要精确控制索引、步长最灵活,可完全控制语法稍繁琐
while不确定循环次数逻辑清晰,适合条件等待容易写出死循环
do...while至少执行一次保证首次执行使用场景较少
for...of遍历可迭代对象(数组、Set、Map)语法简洁,语义清晰无法直接获取索引
for...in遍历对象属性直接获取键名遍历原型链属性,需过滤
forEach()函数式遍历数组链式调用,结合箭头函数很简洁无法 break/continue
  1. 九九乘法表:用双重 for 循环打印完整的九九乘法表,要求格式对齐整齐。格式参考:1x1=1, 1x2=2 2x2=4, ... 直到 9x9=81。使用 padStart 方法确保每个算式等宽显示。
  2. 数组元素查找:给定数组 [12, 45, 23, 67, 34, 89, 56],用 for 循环找到第一个大于 50 的元素及其索引,找到后使用 break 终止循环。再用 for...of 和普通的 for 循环各实现一遍。
  3. FizzBuzz 经典面试题:用 for 循环输出 1 到 100。数字是 3 的倍数输出 "Fizz",是 5 的倍数输出 "Buzz",同时是 3 和 5 的倍数输出 "FizzBuzz",其他情况输出数字本身。
  4. 对象遍历方式对比:创建至少包含 5 个属性的 student 对象(姓名、年龄、班级、成绩、爱好)。分别用 for...in、Object.keys()+for...of、Object.entries()+for...of 三种方式遍历,对比输出结果的差异和各自的适用场景。
  5. 猜数字游戏:用 while 循环实现完整的猜数字游戏。随机生成 1 到 100 之间的整数,每次用 prompt 接收用户猜测,反馈"大了"或"小了",猜对时显示祝贺信息和猜测次数。额外处理:输入非数字的容错,输入 q 退出的功能。
Ctrl+Enter
🚀 升级VIP
解锁全部课程+AI助手

🏆 学习排行

加载中...

📊 统计

📖 231 篇
0 完成
🔥 0