JavaScript 循环结构详解:while 和 for 循环
在编写脚本时,经常需要重复执行相同的操作多次。比如,逐个显示列表中的商品,或者遍历1到10的数字并对每个数字执行相同的代码。JavaScript提供了多种循环结构来处理这类重复性任务,本文将深入解析最基础的两种循环:while和for循环。
为什么需要循环?
想象一下,如果没有循环,要输出数字0到2,你需要这样写:
console.log(0);
console.log(1);
console.log(2);
而当需要输出0到100时,这种重复代码就会变得极其冗长。循环结构正是为了解决这种重复性任务而设计的。
while 循环
基本语法
while循环是最基础的循环结构,其语法格式如下:
while (condition) {
// 循环体代码
}
只要条件表达式condition的值为真(truthy),循环体中的代码就会重复执行。
基础示例
let i = 0;
while (i < 3) {
console.log(i); // 输出: 0, 1, 2
i++;
}
在这个例子中:
i初始值为0- 每次循环检查
i < 3是否为真 - 如果为真,执行循环体(输出i并递增)
- 循环共执行3次迭代(iteration)
单行循环体简化
如果循环体只有一行代码,可以省略花括号:
let i = 3;
while (i) console.log(i--); // 输出: 3, 2, 1
无限循环与中断
let sum = 0;
while (true) {
let value = Number(prompt('请输入一个数字', ''));
if (!value) break; // 如果输入为空或取消,退出循环
sum += value;
}
console.log('总和:', sum);
do...while 循环
语法结构
do...while循环与while循环类似,但条件检查在循环体执行之后:
do {
// 循环体代码
} while (condition);
特点对比
| 循环类型 | 条件检查时机 | 最少执行次数 |
|---|---|---|
| while | 执行前检查 | 0次 |
| do...while | 执行后检查 | 1次 |
示例代码
let i = 0;
do {
console.log(i); // 输出: 0, 1, 2
i++;
} while (i < 3);
for 循环
完整语法结构
for循环是最常用且功能最强大的循环结构:
for (initialization; condition; increment) {
// 循环体代码
}
组成部分详解
基础示例
for (let i = 0; i < 3; i++) {
console.log(i); // 输出: 0, 1, 2
}
变量作用域
在for循环中声明的变量只在循环内部有效:
for (let i = 0; i < 3; i++) {
console.log(i); // 正常工作
}
console.log(i); // 错误: i未定义
灵活的for循环配置
for循环的三个部分都可以根据需要省略:
省略初始化部分:
let i = 0;
for (; i < 3; i++) {
console.log(i);
}
省略步进部分:
let i = 0;
for (; i < 3;) {
console.log(i++);
}
创建无限循环:
for (;;) {
// 无限循环
if (condition) break;
}
循环控制语句
break 语句
break语句用于立即退出整个循环:
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 当i等于5时退出循环
}
console.log(i); // 输出: 0, 1, 2, 3, 4
}
continue 语句
continue语句跳过当前迭代,继续下一次迭代:
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 跳过偶数
}
console.log(i); // 输出: 1, 3, 5, 7, 9
}
标签语句(Label)
标签允许在嵌套循环中控制外层循环:
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outerLoop; // 退出外层循环
}
console.log(`i=${i}, j=${j}`);
}
}
// 输出:
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
性能优化与最佳实践
1. 缓存数组长度
在处理数组时,预先缓存长度可以提高性能:
const arr = [1, 2, 3, 4, 5];
for (let i = 0, len = arr.length; i < len; i++) {
console.log(arr[i]);
}
2. 避免在循环内创建函数
// 不推荐
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
// 推荐:使用块级作用域
for (let i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 100);
}
3. 选择合适的循环类型
| 场景 | 推荐循环 | 原因 |
|---|---|---|
| 已知迭代次数 | for | 结构清晰,易于控制 |
| 条件依赖外部状态 | while | 灵活性高 |
| 至少执行一次 | do...while | 确保执行 |
常见错误与陷阱
1. 无限循环
// 错误示例:缺少递增语句
let i = 0;
while (i < 5) {
console.log(i);
// 忘记 i++,导致无限循环
}
2. 浮点数精度问题
// 由于浮点数精度问题,可能无法准确终止
for (let i = 0; i < 1; i += 0.1) {
console.log(i); // 可能执行次数超出预期
}
3. 修改循环变量
const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 3) {
arr.splice(i, 1); // 修改数组会影响循环
i--; // 需要调整索引
}
}
实战应用示例
1. 数组遍历与处理
const numbers = [1, 2, 3, 4, 5];
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
console.log('总和:', sum); // 输出: 15
2. 字符串处理
const str = "Hello";
let reversed = "";
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
console.log(reversed); // 输出: "olleH"
3. 生成数学序列
// 生成斐波那契数列前10项
let fib = [0, 1];
for (let i = 2; i < 10; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
console.log(fib); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
总结对比表
| 特性 | while | do...while | for |
|---|---|---|---|
| 条件检查时机 | 执行前 | 执行后 | 执行前 |
| 最少执行次数 | 0次 | 1次 | 0次 |
| 适用场景 | 条件复杂 | 至少执行一次 | 已知迭代次数 |
| 变量作用域 | 外部/内部 | 外部/内部 | 可选内部 |
| 代码简洁性 | 中等 | 中等 | 高 |
选择指南
- 使用while循环:当迭代次数不确定,且条件检查需要在循环体执行之前进行时
- 使用do...while循环:当需要确保循环体至少执行一次时
- 使用for循环:当迭代次数已知或需要精确控制循环变量时
掌握这些循环结构是JavaScript编程的基础,它们为处理重复性任务提供了强大而灵活的工具。在实际开发中,根据具体需求选择合适的循环类型,并遵循最佳实践,可以编写出高效、可维护的代码。
记住,良好的循环设计不仅关乎功能实现,更影响代码的性能和可读性。合理使用break、continue和控制语句,可以让你的循环逻辑更加清晰和高效。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



