在编程中,循环语句是实现代码复用和逻辑简化的核心手段之一。当需要重复执行某段代码(如遍历数组、处理批量数据、实现特定次数的运算等)时,循环语句能帮我们摆脱重复编写代码的繁琐,提升开发效率。JavaScript 中提供了多种循环语句,包括for、while、do...while,以及用于遍历可迭代对象的for...in和for...of。本文将逐一拆解它们的语法结构、核心特点、适用场景,并结合实例说明用法,帮助大家快速掌握并灵活运用。
目录
一、基础循环:for 循环(最常用的“计数型”循环)
1. 语法结构
2. 基础示例
3. 特殊用法:省略部分表达式
二、条件循环:while 循环(“未知次数”的循环)
1. 语法结构
2. 基础示例
3. 注意事项
三、do...while 循环(“至少执行一次”的循环)
1. 语法结构
2. 基础示例
3. 与 while 循环的核心区别
四、遍历循环:for...in 与 for...of(针对可迭代对象)
1. for...in 循环:遍历对象的可枚举属性(键名)
语法结构
示例1:遍历对象的属性
示例2:遍历数组(不推荐)
2. for...of 循环:遍历可迭代对象的键值(推荐用于数组、字符串等)
语法结构
示例1:遍历数组(推荐)
示例2:遍历字符串
示例3:遍历 Map(键值对)
for...in 与 for...of 的核心区别
五、循环控制:break 与 continue 语句
1. break 语句:立即退出循环
2. continue 语句:跳过当前迭代,继续下一次
六、总结:各循环语句的适用场景选型
一、基础循环:for 循环(最常用的“计数型”循环)
for循环是 JavaScript 中最经典、最常用的循环语句,尤其适合已知循环次数的场景(如遍历固定长度的数组、执行指定次数的运算)。它将循环的初始化、条件判断、迭代操作集中在一个语句中,结构清晰,可读性强。
1. 语法结构
for (初始化表达式; 条件判断表达式; 迭代表达式) { // 循环体:满足条件时执行的代码块 }各部分作用详解:
初始化表达式:循环开始前执行一次,用于声明循环变量(如
let i = 0),也可省略(若变量已在外部声明)。条件判断表达式:每次循环执行前判断,结果为
true则执行循环体,为false则退出循环。若省略,默认恒为true(易造成死循环,需谨慎)。迭代表达式:每次循环体执行完成后执行,用于更新循环变量(如
i++、i -= 2),可省略(需在循环体内手动更新变量,否则可能死循环)。
2. 基础示例
需求:打印 1 到 5 的数字
for (let i = 1; i <= 5; i++) { console.log(i); // 输出:1 2 3 4 5 }3. 特殊用法:省略部分表达式
场景1:外部声明循环变量,省略初始化表达式
let i = 0; for (; i < 3; i++) { console.log(i); // 输出:0 1 2 }场景2:循环体内更新变量,省略迭代表达式
for (let i = 0; i < 3;) { console.log(i); i++; // 手动更新变量,否则死循环 } // 输出:0 1 2注意:若同时省略三个表达式(for (;;) {}),会形成无限循环,需在循环体内通过break语句手动退出。
二、条件循环:while 循环(“未知次数”的循环)
while循环适用于未知循环次数,仅依赖“条件是否成立”来决定是否执行循环的场景(如等待用户输入正确内容、处理动态获取的数据直到无数据为止)。它的结构相对简洁,仅包含“条件判断”和“循环体”。
1. 语法结构
while (条件判断表达式) { // 循环体:条件为 true 时执行 // (需在循环体内更新条件相关变量,否则易死循环) }执行逻辑:先判断条件,若为true则执行循环体,执行完成后再次回到条件判断;若为false,直接退出循环。
2. 基础示例
需求:生成随机数,直到生成的数字大于 0.5 为止
let randomNum; while (randomNum <= 0.5 || randomNum === undefined) { randomNum = Math.random(); // 生成 0~1 之间的随机数 console.log("当前随机数:", randomNum); } // 输出:多次打印随机数,直到某次数值 > 0.53. 注意事项
1. 循环体内必须包含“更新条件”的逻辑(如上述示例中randomNum = Math.random()),否则若初始条件为true,会陷入无限循环。
2. 若初始条件为false,循环体可能一次都不执行(这是while循环的核心特点)。
三、do...while 循环(“至少执行一次”的循环)
do...while循环是while循环的变体,它的核心区别的是:先执行一次循环体,再判断条件。因此,无论条件是否成立,循环体至少会执行一次。适用于“必须先执行一次操作,再根据结果判断是否继续”的场景(如表单验证:先提交一次,再判断是否符合规则,不符合则重新提交)。
1. 语法结构
do { // 循环体:先执行一次 } while (条件判断表达式); // 执行后判断,true 则继续循环2. 基础示例
需求:让用户输入数字,若输入的不是数字,则重新输入(至少输入一次)
let num; do { num = prompt("请输入一个数字:"); // 先执行一次输入 } while (isNaN(num)); // 若输入的不是数字(isNaN 返回 true),则继续循环 console.log("你输入的数字是:", num);3. 与 while 循环的核心区别
循环类型 | 执行顺序 | 循环体是否可能一次不执行 |
|---|---|---|
while | 先判断条件,再执行循环体 | 是(初始条件为 false 时) |
do...while | 先执行循环体,再判断条件 | 否(至少执行一次) |
四、遍历循环:for...in 与 for...of(针对可迭代对象)
前面的for、while、do...while更适合“计数型”或“条件型”循环,而for...in和for...of专门用于遍历可迭代对象(如数组、对象、字符串、Map、Set 等)。两者的核心区别在于:遍历的目标不同(for...in遍历“键名”,for...of遍历“键值”)。
1. for...in 循环:遍历对象的可枚举属性(键名)
for...in主要用于遍历对象的可枚举属性(包括自身属性和继承的原型属性),也可用于遍历数组(但遍历的是数组的索引,而非元素值,不推荐用于数组遍历,易出现问题)。
语法结构
for (const 键名变量 in 可迭代对象) { // 循环体:每次遍历得到一个键名 }示例1:遍历对象的属性
const person = { name: "张三", age: 25, gender: "男" }; for (const key in person) { console.log("键名:", key, ",键值:", person[key]); } // 输出: // 键名: name ,键值: 张三 // 键名: age ,键值: 25 // 键名: gender ,键值: 男示例2:遍历数组(不推荐)
const arr = [10, 20, 30]; for (const index in arr) { console.log("索引:", index, ",元素值:", arr[index]); // 索引是字符串类型 } // 输出: // 索引: 0 ,元素值: 10 // 索引: 1 ,元素值: 20 // 索引: 2 ,元素值: 30不推荐用for...in遍历数组的原因:1. 遍历的索引是字符串类型,若进行数值运算需转换;2. 会遍历数组原型上的可枚举属性,导致结果混乱;3. 遍历顺序可能不固定。
2. for...of 循环:遍历可迭代对象的键值(推荐用于数组、字符串等)
for...of是 ES6 新增的循环语句,专门用于遍历可迭代对象的键值(如数组的元素、字符串的字符、Map 的值等)。它避免了for...in的缺点,语法简洁,是遍历数组、字符串等的首选方式。
语法结构
for (const 键值变量 of 可迭代对象) { // 循环体:每次遍历得到一个键值 }示例1:遍历数组(推荐)
const arr = [10, 20, 30]; for (const value of arr) { console.log("元素值:", value); // 直接获取元素值,无需通过索引 } // 输出:10 20 30示例2:遍历字符串
const str = "hello"; for (const char of str) { console.log("字符:", char); } // 输出:h e l l o示例3:遍历 Map(键值对)
const map = new Map([["name", "李四"], ["age", 30]]); for (const [key, value] of map) { // 解构赋值获取键名和键值 console.log("键名:", key, ",键值:", value); } // 输出: // 键名: name ,键值: 李四 // 键名: age ,键值: 30for...in 与 for...of 的核心区别
循环类型 | 遍历目标 | 适用对象 | 是否遍历原型属性 |
|---|---|---|---|
for...in | 键名(对象属性名、数组索引) | 对象、数组(不推荐) | 是(易混乱) |
for...of | 键值(数组元素、字符串字符等) | 数组、字符串、Map、Set 等可迭代对象 | 否(仅遍历自身) |
五、循环控制:break 与 continue 语句
在循环过程中,有时需要手动控制循环的执行(如提前退出循环、跳过某次循环),此时需要用到break和continue语句。
1. break 语句:立即退出循环
break用于立即终止当前循环,跳出循环体,不再执行后续的循环迭代。适用于“找到目标值后直接退出”“满足某个条件时停止循环”的场景。
// 需求:遍历数组,找到值为 20 的元素后立即退出 const arr = [10, 20, 30, 40]; for (const value of arr) { if (value === 20) { break; // 找到目标值,退出循环 } console.log(value); } // 输出:10(仅打印 10,找到 20 后退出)2. continue 语句:跳过当前迭代,继续下一次
continue用于跳过当前循环的剩余代码,直接进入下一次迭代(不会退出循环,仅跳过本次)。适用于“过滤某些条件,不执行本次循环体”的场景。
// 需求:遍历 1~5 的数字,跳过偶数,只打印奇数 for (let i = 1; i <= 5; i++) { if (i % 2 === 0) { continue; // 是偶数,跳过本次循环 } console.log(i); } // 输出:1 3 5六、总结:各循环语句的适用场景选型
掌握循环语句的核心是“根据场景选对类型”,以下是各循环的适用场景总结,帮助大家快速决策:
for 循环:已知循环次数(如遍历固定长度数组、执行 N 次运算),结构清晰,首选。
while 循环:未知循环次数,依赖条件判断(如等待某个状态变化),初始条件可能为 false(循环体可能不执行)。
do...while 循环:未知循环次数,但必须先执行一次循环体(如表单验证、强制输入)。
for...in 循环:遍历对象的可枚举属性(键名),不推荐用于数组。
for...of 循环:遍历可迭代对象的键值(数组元素、字符串字符等),是数组、字符串遍历的首选。
最后,提醒大家:编写循环时,务必避免无限循环(确保条件会最终变为 false,或通过break手动退出);同时,根据代码可读性选择合适的循环类型,让后续维护更高效。