Skip to content

条件语句:让程序学会做决策

每天早上起床,你会根据天气决定穿什么衣服:如果下雨就带伞,如果天冷就穿外套,如果天气好就穿短袖。这种"如果...那么..."的决策过程,在编程中就是通过条件语句来实现的。条件语句是程序的"大脑",让代码能够根据不同情况做出不同的反应。

什么是条件语句

条件语句允许程序根据特定条件的真假来决定执行哪段代码。就像一个分岔路口,程序会根据路标(条件)选择不同的道路前进。在 JavaScript 中,最基本的条件语句就是 if 语句。

当你写下一个 if 语句时,你实际上是在告诉程序:"检查这个条件,如果条件为真,就执行这段代码;如果为假,就跳过。"这个过程非常直观,就像人类的思考方式一样。

基本 if 语句

最简单的 if 语句只包含一个条件和一段代码块:

javascript
let temperature = 28;

if (temperature > 25) {
  console.log("Today is hot, wear light clothes!");
}

在这个例子中,程序会检查温度是否大于 25 度。如果是,就输出建议穿轻便衣服的信息。如果温度不超过 25 度,这段输出语句就会被完全跳过,程序继续执行后面的代码。

条件表达式(temperature > 25)会被求值为布尔值 truefalse。只有当结果是 true 时,花括号内的代码才会执行。这里的花括号 {} 定义了一个代码块,是条件语句的执行范围。

如果条件语句只包含一行代码,技术上可以省略花括号:

javascript
if (temperature > 25) console.log("It's hot!");

但这种写法不推荐,因为如果后续需要添加更多代码,容易出错。始终使用花括号是一个好习惯,让代码更清晰、更易维护。

if-else 语句:二选一

现实中很多决策不是"做或不做",而是"这样做或那样做"。比如,如果下雨就带伞,否则就不带。这就需要 if-else 语句:

javascript
let isRaining = true;

if (isRaining) {
  console.log("Take an umbrella!");
} else {
  console.log("Enjoy the sunshine!");
}

else 分支定义了当条件为假时应该执行的代码。无论 isRainingtrue 还是 false,程序都会执行其中一个分支,不会两个都执行,也不会都不执行。这种"非此即彼"的结构在编程中非常常见。

让我们看一个更实际的例子,判断用户是否有权限访问某个功能:

javascript
let userAge = 16;
let canVote = false;

if (userAge >= 18) {
  canVote = true;
  console.log("You are eligible to vote.");
} else {
  canVote = false;
  console.log("You are not old enough to vote yet.");
}

console.log(`Voting status: ${canVote}`); // Voting status: false

else if:多条件判断

当需要检查多个互斥的条件时,else if 就派上用场了。想象一个成绩评级系统,根据不同的分数段给出不同的等级:

javascript
let score = 85;
let grade;

if (score >= 90) {
  grade = "A";
  console.log("Excellent work!");
} else if (score >= 80) {
  grade = "B";
  console.log("Good job!");
} else if (score >= 70) {
  grade = "C";
  console.log("You passed.");
} else if (score >= 60) {
  grade = "D";
  console.log("You need improvement.");
} else {
  grade = "F";
  console.log("You failed. Please study harder.");
}

console.log(`Your grade is: ${grade}`); // Your grade is: B

这里的关键点是,条件是按顺序检查的,一旦找到第一个为真的条件,就执行对应的代码块,然后跳过所有剩余的 else ifelse 分支。在上面的例子中,虽然 score >= 80score >= 70 等条件也为真,但因为 score >= 90 是假的而 score >= 80 首先为真,所以只有第二个分支被执行。

条件的顺序很重要。如果你把条件写反了,程序的行为就会完全不同:

javascript
let score = 85;

// ❌ 错误的顺序
if (score >= 60) {
  console.log("You need improvement."); // 这会被执行
} else if (score >= 70) {
  console.log("You passed.");
} else if (score >= 80) {
  console.log("Good job!");
} else if (score >= 90) {
  console.log("Excellent work!");
}

在这个错误的例子中,因为 85 大于 60,第一个条件就为真了,程序不会继续检查后面更精确的条件。所以在使用 else if 链时,要从最严格的条件开始检查,或者使用独立的 if 语句。

嵌套条件语句

有时候,你需要在一个条件成立后,再检查另一个条件。这就是嵌套条件语句。比如,一个会员系统可能需要同时检查用户是否登录以及是否是高级会员:

javascript
let isLoggedIn = true;
let isPremiumMember = true;

if (isLoggedIn) {
  console.log("Welcome back!");

  if (isPremiumMember) {
    console.log("You have access to premium features.");
  } else {
    console.log("Upgrade to premium for more features!");
  }
} else {
  console.log("Please log in to continue.");
}

虽然嵌套条件很强大,但过深的嵌套会让代码难以阅读和维护。当嵌套层级超过 2-3 层时,就应该考虑重构代码了。一个常见的改进方法是使用逻辑运算符 &&(与)和 ||(或):

javascript
let isLoggedIn = true;
let isPremiumMember = true;

// 使用逻辑与运算符简化
if (isLoggedIn && isPremiumMember) {
  console.log("Welcome back! You have access to premium features.");
} else if (isLoggedIn && !isPremiumMember) {
  console.log("Welcome back! Upgrade to premium for more features.");
} else {
  console.log("Please log in to continue.");
}

另一个技巧是"提前返回"(early return),特别是在函数中:

javascript
function checkAccess(isLoggedIn, isPremiumMember) {
  // 提前返回,减少嵌套
  if (!isLoggedIn) {
    return "Please log in to continue.";
  }

  if (!isPremiumMember) {
    return "Upgrade to premium for more features!";
  }

  return "You have access to premium features.";
}

console.log(checkAccess(true, true)); // You have access to premium features.
console.log(checkAccess(true, false)); // Upgrade to premium for more features!
console.log(checkAccess(false, false)); // Please log in to continue.

三元运算符:简洁的条件表达式

对于简单的二选一场景,JavaScript 提供了一种更简洁的语法:三元运算符(也叫条件运算符)。它的语法是 条件 ? 值1 : 值2,意思是"如果条件为真,返回值 1,否则返回值 2"。

javascript
let age = 20;
let status = age >= 18 ? "adult" : "minor";
console.log(status); // adult

这相当于:

javascript
let age = 20;
let status;

if (age >= 18) {
  status = "adult";
} else {
  status = "minor";
}

三元运算符特别适合用于赋值或直接在表达式中使用:

javascript
let temperature = 15;
console.log(`It's ${temperature > 20 ? "warm" : "cool"} today.`);

// 在函数参数中使用
function greet(name, timeOfDay) {
  console.log(
    `Good ${timeOfDay === "morning" ? "morning" : "evening"}, ${name}!`
  );
}

greet("Alice", "morning"); // Good morning, Alice!
greet("Bob", "evening"); // Good evening, Bob!

但是,不要过度使用三元运算符。嵌套的三元运算符会让代码变得难以理解:

javascript
// ❌ 难以阅读的嵌套三元运算符
let score = 85;
let grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";

// ✅ 这种情况应该使用 if-else if
let score = 85;
let grade;

if (score >= 90) {
  grade = "A";
} else if (score >= 80) {
  grade = "B";
} else if (score >= 70) {
  grade = "C";
} else {
  grade = "F";
}

真值与假值

在条件语句中,JavaScript 会将条件表达式转换为布尔值。但并不是所有值都需要显式地是 truefalse。JavaScript 中有一些值在布尔上下文中被视为"假值"(falsy),其他所有值都被视为"真值"(truthy)。

假值只有 7 个:false0-00n(BigInt 零)、""(空字符串)、nullundefinedNaN

javascript
// 这些都会进入 else 分支
if (0) {
  console.log("Won't print");
} else {
  console.log("0 is falsy"); // 这会执行
}

if ("") {
  console.log("Won't print");
} else {
  console.log("Empty string is falsy"); // 这会执行
}

if (null) {
  console.log("Won't print");
} else {
  console.log("null is falsy"); // 这会执行
}

// 所有其他值都是真值
if ("hello") {
  console.log("Non-empty string is truthy"); // 这会执行
}

if (42) {
  console.log("Non-zero number is truthy"); // 这会执行
}

if ([]) {
  console.log("Empty array is truthy"); // 这会执行!
}

if ({}) {
  console.log("Empty object is truthy"); // 这会执行!
}

这个特性很方便,但也容易出错。常见的陷阱是空数组和空对象是真值:

javascript
let items = [];

if (items) {
  console.log("This will run even though array is empty!");
}

// 正确的检查方式
if (items.length > 0) {
  console.log("Array has items");
} else {
  console.log("Array is empty");
}

实际应用场景

1. 表单验证

条件语句在表单验证中非常常见:

javascript
function validateEmail(email) {
  if (!email) {
    return "Email is required";
  }

  if (!email.includes("@")) {
    return "Invalid email format";
  }

  if (email.length < 5) {
    return "Email is too short";
  }

  return "Email is valid";
}

console.log(validateEmail("")); // Email is required
console.log(validateEmail("invalid")); // Invalid email format
console.log(validateEmail("a@b")); // Email is too short
console.log(validateEmail("[email protected]")); // Email is valid

2. 用户权限检查

javascript
function canDeletePost(user, post) {
  // 管理员可以删除任何帖子
  if (user.role === "admin") {
    return true;
  }

  // 版主可以删除自己版块的帖子
  if (user.role === "moderator" && post.category === user.moderatedCategory) {
    return true;
  }

  // 用户只能删除自己的帖子
  if (post.authorId === user.id) {
    return true;
  }

  return false;
}

let adminUser = { id: 1, role: "admin" };
let regularUser = { id: 2, role: "user" };
let post = { id: 100, authorId: 3, category: "tech" };

console.log(canDeletePost(adminUser, post)); // true
console.log(canDeletePost(regularUser, post)); // false

3. 响应式设计

javascript
function getDeviceType() {
  let width = window.innerWidth;

  if (width < 768) {
    return "mobile";
  } else if (width < 1024) {
    return "tablet";
  } else {
    return "desktop";
  }
}

function adjustLayout() {
  let deviceType = getDeviceType();

  if (deviceType === "mobile") {
    console.log("Show mobile menu");
    console.log("Use single column layout");
  } else if (deviceType === "tablet") {
    console.log("Show tablet menu");
    console.log("Use two column layout");
  } else {
    console.log("Show full menu");
    console.log("Use three column layout");
  }
}

4. API 响应处理

javascript
function handleAPIResponse(response) {
  if (response.status === 200) {
    console.log("Success:", response.data);
    return response.data;
  } else if (response.status === 404) {
    console.log("Error: Resource not found");
    return null;
  } else if (response.status === 500) {
    console.log("Error: Server error");
    return null;
  } else {
    console.log("Error: Unknown error");
    return null;
  }
}

常见陷阱与最佳实践

1. 使用 === 而不是 ==

JavaScript 有两种相等比较运算符:==(宽松相等)和 ===(严格相等)。== 会进行类型转换,可能导致意外的结果:

javascript
// ❌ 使用 == 可能导致意外
if (0 == false) {
  console.log("This is true!"); // 会执行
}

if ("" == false) {
  console.log("This is also true!"); // 会执行
}

// ✅ 使用 === 更安全
if (0 === false) {
  console.log("Won't execute");
}

if ("5" === 5) {
  console.log("Won't execute");
}

if ("5" == 5) {
  console.log("Will execute with =="); // 会执行
}

几乎在所有情况下,都应该使用 ===!==,除非你明确知道需要类型转换。

2. 避免过长的条件链

else if 链过长时,考虑使用其他方式:

javascript
// ❌ 过长的 else if 链
function getColorName(code) {
  if (code === "#FF0000") {
    return "Red";
  } else if (code === "#00FF00") {
    return "Green";
  } else if (code === "#0000FF") {
    return "Blue";
  } else if (code === "#FFFF00") {
    return "Yellow";
  } else if (code === "#FF00FF") {
    return "Magenta";
  } else {
    return "Unknown";
  }
}

// ✅ 使用对象查找
function getColorName(code) {
  const colorMap = {
    "#FF0000": "Red",
    "#00FF00": "Green",
    "#0000FF": "Blue",
    "#FFFF00": "Yellow",
    "#FF00FF": "Magenta",
  };

  return colorMap[code] || "Unknown";
}

3. 明确的条件表达式

避免依赖隐式的真值/假值转换,尤其是在条件不明显的情况下:

javascript
// ❌ 不明确
let count = 0;
if (count) {
  console.log("Has items");
}

// ✅ 明确的意图
if (count > 0) {
  console.log("Has items");
}

// ❌ 不明确
let user = null;
if (!user) {
  console.log("No user");
}

// ✅ 更明确
if (user === null || user === undefined) {
  console.log("No user");
}

4. 处理边界情况

始终考虑边界情况和异常输入:

javascript
function getDiscount(age) {
  // ✅ 处理无效输入
  if (typeof age !== "number" || age < 0) {
    return 0;
  }

  if (age < 12) {
    return 0.5; // 儿童半价
  } else if (age >= 65) {
    return 0.3; // 老年人7折
  } else {
    return 0; // 无折扣
  }
}

console.log(getDiscount(-5)); // 0
console.log(getDiscount("young")); // 0
console.log(getDiscount(10)); // 0.5
console.log(getDiscount(70)); // 0.3

总结

条件语句是编程的基础构建块之一,让程序能够根据不同情况做出决策。掌握 ifelse ifelse 和三元运算符的使用,理解真值和假值的概念,能够帮助你编写更灵活、更智能的代码。

关键要点:

  • 使用 if 语句执行条件性代码
  • else if 可以串联多个互斥条件
  • 三元运算符适合简单的二选一场景
  • 始终使用 === 进行比较
  • 注意条件的顺序和边界情况
  • 保持代码清晰,避免过深的嵌套
  • 考虑使用对象查找或其他模式替代过长的条件链

理解并熟练运用条件语句,是成为优秀程序员的第一步。随着实践的积累,你会越来越擅长用条件语句构建复杂的程序逻辑。