前置知识: JavaScript

控制流

5 minIntermediate

条件判断、循环结构与迭代方法。

1. 条件分支 (Conditionals)

1.1 if-else 语句

基本语法

if (condition) {
  // 条件为真时执行
} else if (anotherCondition) {
  // 另一个条件为真时执行
} else {
  // 所有条件都为假时执行
}

示例

const score = 85;
if (score >= 90) {
  console.log('优秀');
} else if (score >= 80) {
  console.log('良好');
} else if (score >= 60) {
  console.log('及格');
} else {
  console.log('不及格');
}
// 输出: 良好

1.2 三元运算符

语法condition ? expression1 : expression2 示例

const age = 18;
const canVote = age >= 18 ? '可以投票' : '不能投票';
console.log(canVote); // 输出: 可以投票

1.3 switch 语句

基本语法

switch (expression) {
  case value1:
    // 当 expression === value1 时执行
    break;
  case value2:
    // 当 expression === value2 时执行
    break;
  default: // 当没有匹配的 case 时执行
}

示例

const day = new Date().getDay();
let dayName;
switch (day) {
  case 0:
    dayName = '星期日';
    break;
  case 1:
    dayName = '星期一';
    break;
  case 2:
    dayName = '星期二';
    break;
  case 3:
    dayName = '星期三';
    break;
  case 4:
    dayName = '星期四';
    break;
  case 5:
    dayName = '星期五';
    break;
  case 6:
    dayName = '星期六';
    break;
  default:
    dayName = '无效的日期';
}
console.log(dayName);

注意:switch 语句使用严格相等 (===) 进行比较,且每个 case 语句后需要使用 break 语句来避免穿透。

2. 循环结构 (Loops)

2.1 for 循环

基本语法

for (initialization; condition; increment) {
  // 循环体
}

示例

// 计算 1 到 10 的和
let sum = 0;
for (let i = 1; i <= 10; i++) {
  sum += i;
}
console.log(sum); // 输出: 55
// 遍历数组
const fruits = ['apple', 'banana', 'orange'];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}
// 输出:
// apple
// banana
// orange

2.2 while 循环

基本语法

while (condition) {
  // 循环体
}

示例

// 计算 1 到 10 的和
let sum = 0;
let i = 1;
while (i <= 10) {
  sum += i;
  i++;
}
console.log(sum); // 输出: 55

2.3 do-while 循环

基本语法

do {
  // 循环体
} while (condition);

示例

// 至少执行一次循环
let count = 0;
do {
  console.log(`计数: ${count}`);
  count++;
} while (count < 3);
// 输出:
// 计数: 0
// 计数: 1
// 计数: 2

2.4 for-in 循环

基本语法

for (variable in object) {
  // 循环体
}

示例

const person = {
  name: '张三',
  age: 30,
  city: '北京',
};
for (let key in person) {
  console.log(`${key}: ${person[key]}`);
}
// 输出:
// name: 张三
// age: 30
// city: 北京

注意:for-in 循环会遍历对象的所有可枚举属性,包括继承的属性。

2.5 for-of 循环 (ES6+)

基本语法

for (variable of iterable) {
  // 循环体
}

示例

 // 遍历数组
 const fruits = ['apple', 'banana', 'orange'];
 for (let fruit of fruits) {
  console.log(fruit);
 }
 // 输出:
 // apple
 // banana
 // orange
 // 遍历字符串
 const str = 'Hello';
 for (let char of str) {
  console.log(char);
 }
 // 输出:
 // H
 // e
 // l
 // l
 // o
 // 遍历 Map
 const map = new Map([
  ['name', '张三'],
  ['age', 30]
 ]
 for (let [key, value] of map) {
  console.log(`${key}: ${value}`);
 }
 // 输出:
 // name: 张三
 // age: 30

3. 跳转语句 (Jumps)

3.1 break 语句

作用:跳出循环或 switch 语句。 示例

// 跳出循环
for (let i = 0; i < 10; i++) {
  if (i === 5) {
    break; // 当 i 等于 5 时跳出循环
  }
  console.log(i);
}
// 输出: 0 1 2 3 4
// 跳出 switch 语句
const fruit = 'apple';
switch (fruit) {
  case 'apple':
    console.log('这是苹果');
    break;
  case 'banana':
    console.log('这是香蕉');
    break;
  default:
    console.log('未知水果');
}
// 输出: 这是苹果

3.2 continue 语句

作用:跳过当前迭代,继续下一次循环。 示例

// 跳过奇数
for (let i = 0; i < 10; i++) {
  if (i % 2 !== 0) {
    continue; // 跳过奇数
  }
  console.log(i);
}
// 输出: 0 2 4 6 8

3.3 return 语句

作用:从函数中返回值,并终止函数执行。 示例

function add(a, b) {
  return a + b; // 返回 a + b 的值
}
const result = add(2, 3);
console.log(result); // 输出: 5
// 提前返回
function checkAge(age) {
  if (age < 18) {
    return '未成年';
  }
  return '成年';
}
console.log(checkAge(16)); // 输出: 未成年
console.log(checkAge(20)); // 输出: 成年

4. 异常处理 (Error Handling)

4.1 try-catch-finally 语句

基本语法

try {
  // 可能抛出异常的代码
} catch (error) {
  // 捕获并处理异常
} finally {
  // 无论是否发生异常都会执行的代码
}

示例

try {
  const result = 10 / 0;
  console.log(result);
} catch (error) {
  console.error('发生错误:', error.message);
} finally {
  console.log('无论是否发生错误,都会执行这里');
}
// 输出:
// 发生错误: Division by zero
// 无论是否发生错误,都会执行这里

4.2 自定义异常

示例

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
  }
}
function validateEmail(email) {
  if (!email.includes('@')) {
    throw new ValidationError('邮箱格式不正确');
  }
  return true;
}
try {
  validateEmail('invalid-email');
  console.log('邮箱验证通过');
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('验证错误:', error.message);
  } else {
    console.error('其他错误:', error.message);
  }
}
// 输出: 验证错误: 邮箱格式不正确

5. 现代迭代方法

5.1 forEach 方法

作用:遍历数组的每个元素。 示例

const fruits = ['apple', 'banana', 'orange'];
fruits.forEach((fruit, index) => {
  console.log(`${index}: ${fruit}`);
});
// 输出:
// 0: apple
// 1: banana
// 2: orange

5.2 map 方法

作用:创建一个新数组,其中包含对原始数组每个元素调用函数的结果。 示例

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // 输出: [2, 4, 6, 8, 10]

5.3 filter 方法

作用:创建一个新数组,其中包含通过测试函数的元素。 示例

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers); // 输出: [2, 4]

5.4 reduce 方法

作用:对数组中的所有元素执行一个 reducer 函数,将其简化为单个值。 示例

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);
console.log(sum); // 输出: 15

6. 最佳实践

6.1 条件分支最佳实践

  1. 使用卫语句:对于复杂的条件逻辑,使用卫语句可以提高代码可读性。
// 不好的做法
function processUser(user) {
  if (user) {
    if (user.isActive) {
      if (user.age >= 18) {
        // 处理逻辑
      }
    }
  }
}
// 好的做法
function processUser(user) {
  if (!user) return;
  if (!user.isActive) return;
  if (user.age < 18) return;
  // 处理逻辑
}
  1. 使用三元运算符:对于简单的条件赋值,使用三元运算符可以使代码更简洁。
  2. 使用 switch 语句:对于多个互斥的条件,使用 switch 语句比多个 if-else 语句更清晰。

6.2 循环最佳实践

  1. 优先使用 for-of 循环:对于数组、字符串等可迭代对象,使用 for-of 循环比传统的 for 循环更简洁。
  2. 使用现代数组方法:对于数组操作,优先使用 forEach、map、filter 等现代数组方法,它们更具可读性。
  3. 避免无限循环:确保循环条件最终会变为 false,避免无限循环。
  4. 注意循环性能:对于大型数组,要注意循环的性能,避免在循环内部进行复杂的计算。

6.3 异常处理最佳实践

  1. 只捕获预期的异常:不要捕获所有异常,只捕获你能够处理的异常。
  2. 使用具体的异常类型:创建和使用具体的异常型,以便更精确地处理不同型的错误。
  3. 保持 try 块小:try 块应该只包含可能抛出异常的代码,这样可以更精确地定位错误。
  4. 使用 finally 清理资源:对于需要清理的资源(如文件句柄、网络连接等),使用 finally 块确保它们被正确清理。

7. 实际应用示例

7.1 示例 1:用户输入验证

function validateUserInput(input) {
  try {
    if (!input) {
      throw new Error('输入不能为空');
    }
    if (input.length < 3) {
      throw new Error('输入长度不能少于 3 个字符');
    }
    if (!/^[a-zA-Z0-9]+$/.test(input)) {
      throw new Error('输入只能包含字母和数字');
    }
    console.log('输入验证通过');
    return true;
  } catch (error) {
    console.error('验证错误:', error.message);
    return false;
  }
}
// 测试
validateUserInput(''); // 输入不能为空
validateUserInput('ab'); // 输入长度不能少于 3 个字符
validateUserInput('abc123'); // 输入验证通过
validateUserInput('abc@123'); // 输入只能包含字母和数字

7.2 示例 2:数据处理

const data = [
  { name: '张三', age: 25, score: 85 },
  { name: '李四', age: 30, score: 92 },
  { name: '王五', age: 22, score: 78 },
  { name: '赵六', age: 28, score: 95 },
];
// 过滤出分数大于 90 的用户
const highScorers = data.filter((user) => user.score > 90);
console.log('高分用户:', highScorers);
// 计算平均年龄
const averageAge = data.reduce((sum, user) => sum + user.age, 0) / data.length;
console.log('平均年龄:', averageAge);
// 生成用户名称列表
const names = data.map((user) => user.name);
console.log('用户名称:', names);

更新日志 (Changelog)

  • 2026-04-05: 整合 JS 控制流与异常处理细节。
  • 2026-04-05: 扩写内容,增加详细的控制流语句、示例和最佳实践。