JavaScript while 和 do…while 循环
简介
循环用于重复执行一段代码。JavaScript 提供了多种循环方式,本文重点介绍 while 和 do...while 两种循环语句。
如果你知道循环的具体次数,通常使用
for循环更合适;如果循环次数不确定,则while和do...while更合适。
while 循环
基本语法
while (condition) {
// 只要 condition 为真,就重复执行这里的代码
}
执行流程:
- 判断
condition条件 - 如果为真,执行循环体
- 执行完后回到步骤 1
- 如果为假,跳出循环
示例
// 从 1 数到 5
let i = 1;
while (i <= 5) {
console.log(i);
i++; // 别忘了更新循环变量,否则会无限循环!
}
// 输出:1 2 3 4 5
注意事项
必须更新循环变量(或改变条件状态):
// 错误的写法:无限循环!
let i = 1;
while (i <= 5) {
console.log(i);
// 忘记 i++ 了!
}
// 正确的写法
let i = 1;
while (i <= 5) {
console.log(i);
i++; // 更新循环变量
}
循环变量可以在循环体内定义,但要小心作用域:
// 常见写法:循环变量在外部定义
let count = 0;
while (count < 3) {
console.log('count:', count);
count++;
}
// 使用场景:读取未知长度的数据时
let data = [1, 2, 3, 4, 5];
let index = 0;
while (index < data.length) {
console.log(data[index]);
index++;
}
常见使用场景
场景 1:处理不确定次数的操作
// 模拟不断接收消息,直到收到 "exit"
let messages = ['hello', 'world', 'exit'];
let i = 0;
while (i < messages.length && messages[i] !== 'exit') {
console.log('收到消息:', messages[i]);
i++;
}
// 输出:收到消息: hello 收到消息: world
场景 2:等待某个条件满足
// 模拟等待某个异步操作完成(简化示例)
let isReady = false;
let attempts = 0;
while (!isReady && attempts < 3) {
console.log('等待中... 尝试次数:', attempts);
attempts++;
// 模拟某个条件达成
if (attempts === 2) {
isReady = true;
}
}
console.log('准备就绪!');
场景 3:输入验证(配合 prompt 等)
// 浏览器环境示例(Node.js 中需其他方式获取输入)
// let age;
// while (isNaN(age) || age < 0 || age > 150) {
// age = parseInt(prompt('请输入有效年龄 (0-150):'));
// }
// console.log('你的年龄是:', age);
do…while 循环
基本语法
do {
// 至少执行一次,然后判断 condition
} while (condition);
执行流程:
- 先执行一次循环体
- 判断
condition条件 - 如果为真,回到步骤 1
- 如果为假,跳出循环
与 while 的关键区别
while:先判断,后执行(可能一次都不执行)
let x = 10;
while (x < 5) {
console.log('这句话不会执行');
x++;
}
console.log('x =', x); // x = 10(循环体没执行)
do…while:先执行,后判断(至少执行一次)
let y = 10;
do {
console.log('这句话会执行一次');
y++;
} while (y < 5);
console.log('y =', y); // y = 11(循环体执行了一次)
示例
// 至少执行一次的示例
let count = 0;
do {
console.log('当前 count:', count);
count++;
} while (count < 3);
// 输出:
// 当前 count: 0
// 当前 count: 1
// 当前 count: 2
适用场景
场景 1:菜单选择(至少显示一次)
// 模拟简单的菜单选择(浏览器环境)
// let choice;
// do {
// choice = prompt('选择操作: 1-新建 2-打开 3-保存 0-退出');
// switch (choice) {
// case '1': console.log('新建文件'); break;
// case '2': console.log('打开文件'); break;
// case '3': console.log('保存文件'); break;
// case '0': console.log('退出'); break;
// default: console.log('无效选择');
// }
// } while (choice !== '0');
场景 2:至少要尝试一次的操作
// 模拟重试机制
let maxRetries = 3;
let attempt = 0;
let success = false;
do {
attempt++;
console.log(`尝试第 ${attempt} 次...`);
// 模拟某次成功
if (attempt === 2) {
success = true;
console.log('成功!');
}
} while (!success && attempt < maxRetries);
if (!success) {
console.log('达到最大重试次数,失败');
}
场景 3:读取用户输入直到有效(至少询问一次)
// let input;
// do {
// input = prompt('请输入非空的用户名:');
// } while (!input || input.trim() === '');
// console.log('用户名:', input);
break 和 continue
两种循环都支持 break 和 continue 来控制循环流程。
break:跳出整个循环
// while 中使用 break
let i = 1;
while (i <= 10) {
if (i === 5) {
break; // 当 i 等于 5 时,跳出整个循环
}
console.log(i);
i++;
}
// 输出:1 2 3 4
// do...while 中使用 break
let j = 1;
do {
if (j === 3) {
break;
}
console.log(j);
j++;
} while (j <= 5);
// 输出:1 2
continue:跳过本次循环,进入下一次
// while 中使用 continue
let i = 0;
while (i < 5) {
i++;
if (i === 3) {
continue; // 跳过 i === 3 时的后续代码
}
console.log(i);
}
// 输出:1 2 4 5(没有 3)
// do...while 中使用 continue
let j = 0;
do {
j++;
if (j === 2 || j === 4) {
continue;
}
console.log(j);
} while (j < 5);
// 输出:1 3 5(没有 2 和 4)
注意事项
// continue 在 while 循环中要小心更新变量
let i = 0;
while (i < 5) {
if (i === 2) {
i++; // 必须更新,否则会无限循环
continue;
}
console.log(i);
i++;
}
// 输出:0 1 3 4
无限循环
如何避免无限循环
// 危险:无限循环!
// while (true) {
// console.log('永不停止');
// }
// 危险:条件永远为真
// let x = 5;
// while (x > 0) {
// console.log(x);
// // 忘记 x-- 了!
// }
// 安全:确保循环条件最终会变为假
let count = 0;
while (count < 100) {
console.log(count);
count++;
}
故意使用无限循环的场景
有时无限循环是有用的,配合 break 控制退出时机。
// 游戏主循环
// while (true) {
// // 处理输入
// // 更新游戏状态
// // 渲染画面
//
// if (gameOver) {
// break; // 游戏结束,退出循环
// }
// }
// 服务器监听
// while (true) {
// let request = await getNextRequest();
// if (request === null) break;
// handleRequest(request);
// }
while vs for:如何选择
| 特性 | while | for |
|---|---|---|
| 循环次数 | 不确定次数时更合适 | 确定次数时更合适 |
| 语法简洁性 | 循环变量需在外部定义 | 变量初始化、条件、更新都在一行 |
| 可读性 | 适合条件复杂的场景 | 适合简单的计数循环 |
| 循环变量作用域 | 在外部可见 | 可在循环内定义(let) |
对比示例
// 用 while:循环次数不确定
let num = Math.random() * 100;
let guesses = 0;
while (num > 10) {
num = Math.random() * 100;
guesses++;
}
console.log(`用了 ${guesses} 次才得到 <= 10 的数`);
// 用 for:循环次数确定
for (let i = 0; i < 5; i++) {
console.log(i);
}
// 更简洁,变量 i 的作用域在循环内
相互转换
// while 循环
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
// 等价的 for 循环
for (let i = 0; i < 5; i++) {
console.log(i);
}
综合示例
示例 1:猜数字游戏
function guessNumber() {
let target = Math.floor(Math.random() * 100) + 1; // 1-100 的随机数
let attempts = 0;
let guess;
console.log('我想了一个 1-100 之间的数字,来猜猜看!');
do {
// guess = parseInt(prompt('请输入你的猜测 (1-100):'));
// 这里用随机模拟,实际环境用 prompt
guess = Math.floor(Math.random() * 100) + 1;
attempts++;
if (guess < target) {
console.log('太小了!');
} else if (guess > target) {
console.log('太大了!');
} else {
console.log(`恭喜!你用了 ${attempts} 次猜中了数字 ${target}!`);
}
} while (guess !== target && attempts < 10); // 限制最多 10 次
if (guess !== target) {
console.log(`游戏结束!正确答案是 ${target}`);
}
}
// guessNumber(); // 调用函数开始游戏
示例 2:数组处理(寻找满足条件的元素)
function findFirstNegative(arr) {
let i = 0;
let result = null;
while (i < arr.length) {
if (arr[i] < 0) {
result = { value: arr[i], index: i };
break; // 找到第一个就退出
}
i++;
}
return result;
}
console.log(findFirstNegative([1, 3, 5, -2, 4])); // { value: -2, index: 3 }
console.log(findFirstNegative([1, 2, 3])); // null
示例 3:数字反转
function reverseNumber(num) {
let original = num;
let reversed = 0;
while (num > 0) {
let digit = num % 10; // 取最后一位
reversed = reversed * 10 + digit; // 拼接到结果
num = Math.floor(num / 10); // 去掉最后一位
}
return reversed;
}
console.log(reverseNumber(12345)); // 54321
console.log(reverseNumber(100)); // 1(注意:前导零会被去掉)
示例 4:密码验证(至少尝试一次)
function verifyPassword(correctPassword) {
let input;
let attempts = 0;
const maxAttempts = 3;
do {
// input = prompt('请输入密码:');
// 模拟输入
input = attempts === 1 ? correctPassword : 'wrong';
attempts++;
if (input === correctPassword) {
console.log('密码正确!');
return true;
} else if (attempts < maxAttempts) {
console.log(`密码错误,还有 ${maxAttempts - attempts} 次机会`);
}
} while (attempts < maxAttempts);
console.log('超过最大尝试次数,账户已锁定!');
return false;
}
// verifyPassword('123456');
总结:while vs do…while
| 特性 | while | do…while |
|---|---|---|
| 执行顺序 | 先判断,后执行 | 先执行,后判断 |
| 最少执行次数 | 0 次(条件为假时不执行) | 1 次(至少执行一次) |
| 适用场景 | 循环次数不确定,可能不执行 | 循环次数不确定,至少要执行一次 |
| 分号 | 不需要 | 需要(while (condition); 末尾分号) |
选择建议
- 循环体可能不执行 → 使用
while - 循环体至少要执行一次 → 使用
do...while - 循环次数已知 → 考虑使用
for更简洁 - 循环次数不确定 → 使用
while或do...while