Appearance
流程控制
流程控制语句用于控制代码的执行顺序。JavaScript 提供了条件语句和循环语句来实现不同的控制流程。
条件语句
条件语句根据条件决定执行哪些代码。
if 语句
javascript
// 基本 if 语句
let age = 18;
if (age >= 18) {
console.log('已成年');
}
// if...else 语句
let score = 55;
if (score >= 60) {
console.log('及格');
} else {
console.log('不及格');
}
// if...else if...else 语句
let grade = 85;
if (grade >= 90) {
console.log('优秀');
} else if (grade >= 80) {
console.log('良好');
} else if (grade >= 70) {
console.log('中等');
} else if (grade >= 60) {
console.log('及格');
} else {
console.log('不及格');
}
// 条件可以是任何表达式
// 假值:false, 0, '', null, undefined, NaN
let value = 'hello';
if (value) {
console.log('value 是真值'); // 执行
}
let emptyStr = '';
if (emptyStr) {
console.log('不会执行');
}
// 嵌套 if 语句
let hasTicket = true;
let age2 = 20;
if (hasTicket) {
if (age2 >= 18) {
console.log('可以进入');
} else {
console.log('未成年人禁止入内');
}
} else {
console.log('请先购票');
}
// 代码块只有一条语句时可省略花括号(不推荐)
if (age >= 18) console.log('已成年');
// 推荐始终使用花括号
if (age >= 18) {
console.log('已成年');
}switch 语句
javascript
// switch 语句用于多分支选择
let day = 3;
let dayName;
switch (day) {
case 1:
dayName = '星期一';
break; // 必须使用 break 跳出
case 2:
dayName = '星期二';
break;
case 3:
dayName = '星期三';
break;
case 4:
dayName = '星期四';
break;
case 5:
dayName = '星期五';
break;
case 6:
dayName = '星期六';
break;
case 7:
dayName = '星期日';
break;
default:
dayName = '无效的日期';
}
console.log(dayName); // 星期三
// 没有 break 的情况(穿透)
let num = 2;
switch (num) {
case 1:
console.log('一');
// 没有 break,会继续执行下一个 case
case 2:
console.log('二');
case 3:
console.log('三');
break; // 在这里停止
default:
console.log('其他');
}
// 输出:二、三
// 利用穿透特性
let month = 2;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
console.log('31天');
break;
case 4:
case 6:
case 9:
case 11:
console.log('30天');
break;
case 2:
console.log('28或29天');
break;
default:
console.log('无效月份');
}
// switch 使用严格相等比较
let x = '10';
switch (x) {
case 10:
console.log('数字 10');
break;
case '10':
console.log('字符串 10'); // 执行这个
break;
}
// switch 表达式(ES2020+)
// 可以在 switch 中使用表达式
let a = 1, b = 2;
switch (true) {
case a > b:
console.log('a > b');
break;
case a < b:
console.log('a < b'); // 执行
break;
default:
console.log('a = b');
}条件运算符
javascript
// 三元运算符:条件 ? 表达式1 : 表达式2
let age = 20;
let status = age >= 18 ? '成年' : '未成年';
console.log(status); // 成年
// 嵌套三元运算符
let score = 75;
let grade = score >= 90 ? 'A' :
score >= 80 ? 'B' :
score >= 70 ? 'C' :
score >= 60 ? 'D' : 'F';
console.log(grade); // C
// 实际应用
let user = null;
let userName = user ? user.name : '游客';
console.log(userName); // 游客
// 设置默认值
let input = '';
let value = input ? input : '默认值';
console.log(value); // 默认值循环语句
循环语句用于重复执行代码块。
while 循环
javascript
// while 循环:先判断条件,再执行循环体
let i = 0;
while (i < 5) {
console.log(i); // 输出 0, 1, 2, 3, 4
i++;
}
// 注意:必须确保循环条件最终变为 false,否则会无限循环
// let j = 0;
// while (j < 5) {
// console.log(j);
// // 忘记 j++,导致无限循环
// }
// 计算 1 到 100 的和
let sum = 0;
let n = 1;
while (n <= 100) {
sum += n;
n++;
}
console.log(sum); // 5050
// 使用 break 跳出循环
let count = 0;
while (true) { // 无限循环
console.log(count);
count++;
if (count >= 5) {
break; // 跳出循环
}
}
// 使用 continue 跳过当前迭代
let m = 0;
while (m < 10) {
m++;
if (m % 2 === 0) {
continue; // 跳过偶数
}
console.log(m); // 输出奇数:1, 3, 5, 7, 9
}do...while 循环
javascript
// do...while 循环:先执行循环体,再判断条件
// 至少执行一次
let i = 0;
do {
console.log(i); // 输出 0, 1, 2, 3, 4
i++;
} while (i < 5);
// 即使条件一开始就不满足,也会执行一次
let j = 10;
do {
console.log(j); // 输出 10
j++;
} while (j < 5);
// 实际应用:获取用户输入直到有效
let input;
do {
input = prompt('请输入一个正数:');
} while (isNaN(input) || Number(input) <= 0);
// 猜数字游戏
let target = Math.floor(Math.random() * 100) + 1;
let guess;
do {
guess = Number(prompt('猜一个 1-100 的数字:'));
if (guess < target) {
alert('太小了,再试试!');
} else if (guess > target) {
alert('太大了,再试试!');
}
} while (guess !== target);
alert('恭喜你猜对了!');for 循环
javascript
// for 循环:最常用的循环
// for (初始化; 条件; 更新) { 循环体 }
// 基本用法
for (let i = 0; i < 5; i++) {
console.log(i); // 输出 0, 1, 2, 3, 4
}
// for 循环的执行顺序
// 1. 初始化(let i = 0)- 只执行一次
// 2. 条件判断(i < 5)- 为 true 继续执行
// 3. 执行循环体
// 4. 更新(i++)
// 5. 回到第 2 步
// 计算 1 到 100 的和
let sum = 0;
for (let i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum); // 5050
// 遍历数组
let fruits = ['苹果', '香蕉', '橙子'];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
// 倒序遍历
for (let i = fruits.length - 1; i >= 0; i--) {
console.log(fruits[i]);
}
// 省略部分表达式
let i = 0;
for (; i < 5; i++) { // 省略初始化
console.log(i);
}
for (let j = 0; ; j++) { // 省略条件(无限循环)
console.log(j);
if (j >= 5) break;
}
for (;;) { // 省略所有(无限循环)
console.log('无限循环');
break;
}
// 多个变量
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(i, j);
}
// 使用 break 和 continue
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 跳出循环
}
console.log(i); // 输出 0, 1, 2, 3, 4
}
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 跳过偶数
}
console.log(i); // 输出奇数:1, 3, 5, 7, 9
}for...in 循环
javascript
// for...in 遍历对象的可枚举属性
let person = {
name: '张三',
age: 25,
city: '北京'
};
for (let key in person) {
console.log(key + ': ' + person[key]);
}
// 输出:
// name: 张三
// age: 25
// city: 北京
// 遍历数组(不推荐)
let arr = ['a', 'b', 'c'];
for (let index in arr) {
console.log(index, arr[index]);
}
// 输出:0 a, 1 b, 2 c
// 注意:index 是字符串,不是数字
// 遍历数组推荐使用 for...of 或普通 for 循环
// for...in 会遍历继承的属性
let obj = Object.create({ inherited: '继承属性' });
obj.own = '自身属性';
for (let key in obj) {
console.log(key); // own, inherited
}
// 只遍历自身属性
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key); // own
}
}for...of 循环(ES6)
javascript
// for...of 遍历可迭代对象(数组、字符串、Map、Set 等)
let arr = ['a', 'b', 'c'];
for (let value of arr) {
console.log(value); // 输出 a, b, c
}
// 遍历字符串
let str = '你好';
for (let char of str) {
console.log(char); // 输出 你, 好
}
// 遍历 Map
let map = new Map([
['name', '张三'],
['age', 25]
]);
for (let [key, value] of map) {
console.log(key, value);
}
// 遍历 Set
let set = new Set([1, 2, 3, 3]);
for (let value of set) {
console.log(value); // 输出 1, 2, 3
}
// 获取索引
for (let [index, value] of arr.entries()) {
console.log(index, value);
}
// for...of 与 for...in 的区别
let arr2 = ['a', 'b', 'c'];
arr2.foo = 'bar';
for (let key in arr2) {
console.log(key); // 0, 1, 2, foo
}
for (let value of arr2) {
console.log(value); // a, b, c
}循环嵌套
javascript
// 嵌套循环
for (let i = 1; i <= 3; i++) {
for (let j = 1; j <= 3; j++) {
console.log(`i=${i}, j=${j}`);
}
}
// 输出乘法表
for (let i = 1; i <= 9; i++) {
let line = '';
for (let j = 1; j <= i; j++) {
line += `${j}×${i}=${i * j}\t`;
}
console.log(line);
}
// 输出三角形
for (let i = 1; i <= 5; i++) {
let line = '';
for (let j = 1; j <= i; j++) {
line += '*';
}
console.log(line);
}
// 输出金字塔
let n = 5;
for (let i = 1; i <= n; i++) {
let line = '';
// 空格
for (let j = 1; j <= n - i; j++) {
line += ' ';
}
// 星号
for (let k = 1; k <= 2 * i - 1; k++) {
line += '*';
}
console.log(line);
}
// break 和 continue 在嵌套循环中
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // 跳出外层循环
}
console.log(`i=${i}, j=${j}`);
}
}
outer2: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
continue outer2; // 跳到外层循环的下一次迭代
}
console.log(`i=${i}, j=${j}`);
}
}跳转语句
break 语句
javascript
// break 跳出循环
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 跳出循环
}
console.log(i); // 输出 0, 1, 2, 3, 4
}
// break 在 switch 中
let day = 2;
switch (day) {
case 1:
console.log('星期一');
break;
case 2:
console.log('星期二');
break;
default:
console.log('其他');
}
// 带标签的 break
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // 跳出外层循环
}
console.log(`(${i}, ${j})`);
}
}
// 查找数组中的元素
let arr = [1, 2, 3, 4, 5];
let target = 3;
let found = false;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
found = true;
break; // 找到后跳出循环
}
}
console.log(found ? '找到了' : '未找到');continue 语句
javascript
// continue 跳过当前迭代,继续下一次
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 跳过偶数
}
console.log(i); // 输出奇数:1, 3, 5, 7, 9
}
// 过滤数组中的元素
let arr = [1, -2, 3, -4, 5, -6];
let positives = [];
for (let num of arr) {
if (num < 0) {
continue; // 跳过负数
}
positives.push(num);
}
console.log(positives); // [1, 3, 5]
// 带标签的 continue
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === j) {
continue outer; // 跳到外层循环的下一次迭代
}
console.log(`(${i}, ${j})`);
}
}
// 输出:(0,1), (0,2), (1,0), (1,2), (2,0), (2,1)return 语句
javascript
// return 用于函数中,返回值并结束函数
function add(a, b) {
return a + b; // 返回结果
}
let result = add(1, 2);
console.log(result); // 3
// return 提前结束函数
function divide(a, b) {
if (b === 0) {
return '除数不能为 0'; // 提前返回
}
return a / b;
}
console.log(divide(10, 2)); // 5
console.log(divide(10, 0)); // 除数不能为 0
// 没有返回值的函数返回 undefined
function greet(name) {
console.log('Hello, ' + name);
// 没有 return 语句
}
let value = greet('张三'); // 输出:Hello, 张三
console.log(value); // undefined
// return 单独使用
function checkAge(age) {
if (age < 0) {
return; // 提前结束,返回 undefined
}
console.log('年龄有效');
}异常处理
try...catch...finally
javascript
// try...catch 捕获异常
try {
// 可能出错的代码
let result = someUndefinedVariable; // 引用错误
} catch (error) {
// 处理错误
console.log('发生错误:' + error.message);
}
// try...catch...finally
try {
console.log('尝试执行');
throw new Error('自定义错误'); // 抛出错误
} catch (error) {
console.log('捕获错误:' + error.message);
} finally {
console.log('无论如何都会执行'); // 始终执行
}
// 实际应用:解析 JSON
function parseJSON(str) {
try {
return JSON.parse(str);
} catch (error) {
console.log('JSON 解析失败:' + error.message);
return null;
}
}
let data = parseJSON('{"name": "张三"}');
console.log(data); // { name: '张三' }
let invalidData = parseJSON('invalid json');
console.log(invalidData); // null
// 获取错误信息
try {
JSON.parse('invalid');
} catch (error) {
console.log(error.name); // SyntaxError
console.log(error.message); // 错误信息
console.log(error.stack); // 错误堆栈
}throw 语句
javascript
// throw 抛出异常
function divide(a, b) {
if (b === 0) {
throw new Error('除数不能为 0');
}
return a / b;
}
try {
divide(10, 0);
} catch (error) {
console.log(error.message); // 除数不能为 0
}
// 抛出不同类型的错误
function validateAge(age) {
if (typeof age !== 'number') {
throw new TypeError('年龄必须是数字');
}
if (age < 0 || age > 150) {
throw new RangeError('年龄必须在 0-150 之间');
}
return true;
}
try {
validateAge('abc');
} catch (error) {
console.log(error.name); // TypeError
console.log(error.message); // 年龄必须是数字
}
// 自定义错误类型
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError('用户名不能为空');
}
if (!user.email) {
throw new ValidationError('邮箱不能为空');
}
return true;
}
try {
validateUser({ name: '' });
} catch (error) {
if (error instanceof ValidationError) {
console.log('验证错误:' + error.message);
} else {
console.log('其他错误:' + error.message);
}
}
// 抛出任意值(不推荐)
throw '字符串错误'; // 可以,但不推荐
throw 123; // 可以,但不推荐
throw { message: '错误对象' }; // 可以,但不推荐
// 推荐使用 Error 对象
throw new Error('错误信息');实战案例
成绩等级判断
javascript
function getGrade(score) {
// 验证输入
if (typeof score !== 'number' || isNaN(score)) {
throw new TypeError('成绩必须是数字');
}
if (score < 0 || score > 100) {
throw new RangeError('成绩必须在 0-100 之间');
}
// 判断等级
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
if (score >= 60) return 'D';
return 'F';
}
// 测试
try {
console.log(getGrade(95)); // A
console.log(getGrade(72)); // C
console.log(getGrade(55)); // F
console.log(getGrade(150)); // 抛出错误
} catch (error) {
console.log('错误:' + error.message);
}计算器
javascript
function calculator(num1, operator, num2) {
// 转换为数字
num1 = Number(num1);
num2 = Number(num2);
// 验证输入
if (isNaN(num1) || isNaN(num2)) {
throw new Error('操作数必须是数字');
}
// 根据运算符计算
switch (operator) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
if (num2 === 0) {
throw new Error('除数不能为 0');
}
return num1 / num2;
case '%':
return num1 % num2;
case '**':
return num1 ** num2;
default:
throw new Error('不支持的运算符:' + operator);
}
}
// 测试
try {
console.log(calculator(10, '+', 5)); // 15
console.log(calculator(10, '/', 2)); // 5
console.log(calculator(2, '**', 3)); // 8
console.log(calculator(10, '/', 0)); // 抛出错误
} catch (error) {
console.log('计算错误:' + error.message);
}猜数字游戏
javascript
function guessNumberGame() {
// 生成随机数
const target = Math.floor(Math.random() * 100) + 1;
let attempts = 0;
let maxAttempts = 10;
console.log('猜数字游戏开始!范围:1-100');
while (attempts < maxAttempts) {
// 获取用户输入(实际应用中可使用 prompt)
// 这里模拟输入
let guess = Math.floor(Math.random() * 100) + 1;
attempts++;
console.log(`第 ${attempts} 次猜测:${guess}`);
if (guess === target) {
console.log('恭喜你猜对了!');
return;
} else if (guess < target) {
console.log('太小了!');
} else {
console.log('太大了!');
}
}
console.log(`游戏结束!正确答案是 ${target}`);
}
guessNumberGame();打印图案
javascript
// 打印空心正方形
function printHollowSquare(n) {
for (let i = 0; i < n; i++) {
let line = '';
for (let j = 0; j < n; j++) {
// 边界位置打印 *,内部打印空格
if (i === 0 || i === n - 1 || j === 0 || j === n - 1) {
line += '* ';
} else {
line += ' ';
}
}
console.log(line);
}
}
printHollowSquare(5);
// 打印菱形
function printDiamond(n) {
// 上半部分
for (let i = 1; i <= n; i++) {
let line = '';
// 空格
for (let j = 1; j <= n - i; j++) {
line += ' ';
}
// 星号
for (let k = 1; k <= 2 * i - 1; k++) {
line += '*';
}
console.log(line);
}
// 下半部分
for (let i = n - 1; i >= 1; i--) {
let line = '';
// 空格
for (let j = 1; j <= n - i; j++) {
line += ' ';
}
// 星号
for (let k = 1; k <= 2 * i - 1; k++) {
line += '*';
}
console.log(line);
}
}
printDiamond(5);小结
本章学习了 JavaScript 的流程控制:
- 条件语句:if、if...else、if...else if...else、switch
- 循环语句:while、do...while、for、for...in、for...of
- 跳转语句:break、continue、return
- 异常处理:try...catch...finally、throw
下一章我们将学习 函数,了解如何封装可重用的代码块。
