5JavaScript高级程序设计(第4版)

语句

控制流

条件语句循环异常处理

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章:语句(Statements)

一、导读

1.1 本章学习目标

第5章介绍JavaScript的控制流语句。本章核心目标:

  • 掌握条件语句:if、switch
  • 熟练使用各种循环:for、while、for...of、for...in
  • 理解异常处理:try-catch-finally
  • 掌握标签语句:break和continue与标签配合

1.2 为什么本章如此重要

JavaScript的控制流语句与C/Java类似,但有一些独特之处。特别是for...of和for...in的区别,以及try-catch的错误处理机制,是编写健壮JavaScript代码的基础。

1.3 核心问题引导

for...of和for...in有什么本质区别?

JavaScript的switch语句使用什么比较方式?

try-catch-finally中,如果try和finally都有return,哪个生效?

JavaScript有哪些内置错误类型?


二、核心概念详解

5.1 条件语句

javascript
// if-else
let score = 85;
if (score >= 90) {
  console.log("A");
} else if (score >= 80) {
  console.log("B");
} else {
  console.log("C");
}

// switch(使用===比较)
let day = "Monday";
switch (day) {
  case "Monday":
  case "Tuesday":
  case "Wednesday":
  case "Thursday":
  case "Friday":
    console.log("Weekday");
    break;
  case "Saturday":
  case "Sunday":
    console.log("Weekend");
    break;
  default:
    console.log("Invalid");
}

// 三元运算符
let age = 20;
let status = age >= 18 ? "adult" : "minor";

5.2 循环语句

javascript
// for循环
for (let i = 0; i < 5; i++) {
  console.log(i);
}

// for...of(遍历值,ES6)
let arr = ["a", "b", "c"];
for (let value of arr) {
  console.log(value);
}

// for...in(遍历键/索引)
let obj = {a: 1, b: 2, c: 3};
for (let key in obj) {
  console.log(`${key}: ${obj[key]}`);
}

// 注意:for...in会遍历原型链上的属性
// 推荐使用Object.keys()
for (let key of Object.keys(obj)) {
  console.log(`${key}: ${obj[key]}`);
}

// while
let n = 5;
while (n > 0) {
  console.log(n);
  n--;
}

// do-while
let m = 0;
do {
  console.log(m);
  m++;
} while (m < 5);

// break和continue
for (let i = 0; i < 10; i++) {
  if (i === 5) break;      // 跳出循环
  if (i % 2 === 0) continue; // 跳过本次迭代
  console.log(i);  // 1, 3
}

5.3 异常处理

javascript
// try-catch-finally
try {
  let result = 10 / 0;
  if (result === Infinity) {
    throw new Error("Division by zero");
  }
} catch (error) {
  console.error("Error:", error.message);
} finally {
  console.log("Cleanup");  // 总是执行
}

// 自定义错误
class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

try {
  let age = -1;
  if (age < 0) {
    throw new ValidationError("Age cannot be negative");
  }
} catch (error) {
  if (error instanceof ValidationError) {
    console.log("Validation:", error.message);
  } else {
    console.log("Other error:", error.message);
  }
}

// 异步错误处理
async function fetchData() {
  try {
    let response = await fetch("https://api.example.com/data");
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    let data = await response.json();
    return data;
  } catch (error) {
    console.error("Fetch failed:", error);
    throw error;  // 重新抛出
  }
}

5.4 标签语句

javascript
// 标签配合break/continue用于多层循环
let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

outer: for (let i = 0; i < matrix.length; i++) {
  for (let j = 0; j < matrix[i].length; j++) {
    if (matrix[i][j] === 5) {
      console.log(`Found at [${i}][${j}]`);
      break outer;  // 跳出外层循环
    }
  }
}

三、实战案例

3.1 数据验证

javascript
function validateUser(user) {
  const errors = [];
  
  if (!user.name || typeof user.name !== 'string') {
    errors.push("Name is required");
  }
  
  if (!user.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(user.email)) {
    errors.push("Valid email is required");
  }
  
  if (!user.age || user.age < 0 || user.age > 150) {
    errors.push("Valid age is required");
  }
  
  if (errors.length > 0) {
    throw new ValidationError(errors.join(", "));
  }
  
  return true;
}

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

try {
  validateUser({name: "", email: "invalid", age: -1});
} catch (error) {
  console.log(error.message);
}

四、本章小结

第5章讲解了JavaScript的控制流:if/switch条件判断、for/while循环(for...of遍历值,for...in遍历键)、try-catch-finally异常处理、标签语句。


五、思考与练习

思考题

for...of和for...in有什么区别?什么时候用哪个?

switch使用什么比较方式?和if-else有什么不同?

finally块中的代码在什么情况下不会执行?

如何创建自定义错误类型?

编程练习

使用for...of遍历一个Map对象。

实现一个带重试的异步请求函数。

编写一个函数,验证用户输入并抛出适当的错误。


5/14语句
0%