JavaScript 条件判断和三元表达式

简介

在 JavaScript 中,条件判断用于控制程序的执行流程。常用的条件判断方式包括:if...else 语句、switch...case 语句、三元表达式(条件运算符),以及利用逻辑运算符的短路求值。


if…else 语句

基本语法

if (condition) {
  // 条件为真时执行
} else {
  // 条件为假时执行
}

示例

let age = 18;

if (age >= 18) {
  console.log('你已成年');
} else {
  console.log('你还未成年');
}
// 输出:你已成年

else if(多条件判断)

let score = 85;

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

嵌套 if…else

let age = 20;
let hasTicket = true;

if (age >= 18) {
  if (hasTicket) {
    console.log('可以进入');
  } else {
    console.log('需要购票');
  }
} else {
  console.log('年龄不足');
}

省略花括号(不推荐)

当代码块只有一条语句时,可以省略花括号,但不推荐,因为容易引发错误。

// 可以运行,但不推荐
if (true) console.log('Hello');

// 容易出错的情况
if (false)
  console.log('这行不会执行');
  console.log('这行无论条件如何都会执行!'); // 缩进有误导性

假值(falsy)在条件判断中

if 条件会自动将值转为布尔值,以下假值会被判定为假:

if (false) console.log('不会执行');
if (0) console.log('不会执行');
if ('') console.log('不会执行');
if (null) console.log('不会执行');
if (undefined) console.log('不会执行');
if (NaN) console.log('不会执行');

// 以下为真值
if ('0') console.log('会执行');   // 非空字符串为真
if ([]) console.log('会执行');    // 空数组为真
if ({}) console.log('会执行');    // 空对象为真

条件判断中的最佳实践

let value = null;

// 不推荐:与 true/false 直接比较
if (value == true) { ... }
if (value == false) { ... }

// 推荐:直接判断值本身
if (value) { ... }        // 判断是否为真值
if (!value) { ... }       // 判断是否为假值

// 判断是否为 null 或 undefined
if (value == null) { ... }   // == 下 null 和 undefined 都匹配
if (value === null) { ... }  // 只匹配 null
if (value === undefined) { ... } // 只匹配 undefined

switch…case 语句

基本语法

switch (expression) {
  case value1:
    // 当 expression === value1 时执行
    break;
  case value2:
    // 当 expression === value2 时执行
    break;
  default:
    // 以上都不匹配时执行
}

示例

let day = 3;
let dayName;

switch (day) {
  case 1:
    dayName = '星期一';
    break;
  case 2:
    dayName = '星期二';
    break;
  case 3:
    dayName = '星期三';
    break;
  case 4:
    dayName = '星期四';
    break;
  case 5:
    dayName = '星期五';
    break;
  default:
    dayName = '周末';
}

console.log(dayName); // 星期三

break 的重要性

如果省略 break,会发生 fall-through(贯穿),即执行完匹配的 case 后继续执行后续 case。

let num = 1;

switch (num) {
  case 1:
    console.log('one');
    // 没有 break!
  case 2:
    console.log('two');
    // 没有 break!
  case 3:
    console.log('three');
    break;
  case 4:
    console.log('four');
}

// 输出:
// one
// two
// three

利用 fall-through(有意为之)

有时 fall-through 是有用的,当多个 case 需要执行相同代码时:

let month = 2;
let days;

switch (month) {
  case 1:
  case 3:
  case 5:
  case 7:
  case 8:
  case 10:
  case 12:
    days = 31;
    break;
  case 4:
  case 6:
  case 9:
  case 11:
    days = 30;
    break;
  case 2:
    days = 28;
    break;
  default:
    days = -1; // 无效月份
}

console.log(days); // 28

switch 使用严格相等(===)

switch 中的比较使用的是严格相等 ===,不会进行类型转换。

let x = '10';

switch (x) {
  case 10:
    console.log('数字 10');
    break;
  case '10':
    console.log('字符串 "10"');
    break;
}

// 输出:字符串 "10"(不会匹配数字 10)

switch 的替代方案

当 case 较多时,使用对象映射可能更清晰:

// 使用 switch
function getDayNameSwitch(day) {
  switch (day) {
    case 1: return '星期一';
    case 2: return '星期二';
    case 3: return '星期三';
    default: return '未知';
  }
}

// 使用对象映射(更简洁)
function getDayNameMap(day) {
  const days = {
    1: '星期一',
    2: '星期二',
    3: '星期三'
  };
  return days[day] || '未知';
}

三元表达式(条件运算符)

语法

condition ? expr1 : expr2
  • 如果 condition 为真,返回 expr1 的值
  • 如果 condition 为假,返回 expr2 的值

基本示例

let age = 20;
let status = age >= 18 ? '成年' : '未成年';
console.log(status); // 成年

// 等价于:
let status2;
if (age >= 18) {
  status2 = '成年';
} else {
  status2 = '未成年';
}

与 if…else 的选择

适合使用三元表达式的场景:

// 简单的赋值
let isLoggedIn = user ? true : false;

// 设置默认值
let username = inputName || 'Guest';
// 或
let username = inputName !== undefined && inputName !== '' ? inputName : 'Guest';

// 函数返回
function getFee(isMember) {
  return isMember ? '$2.00' : '$10.00';
}

不适合使用三元表达式的场景:

// 不推荐:复杂逻辑用三元表达式会降低可读性
let result = condition1 ? (condition2 ? (condition3 ? 'a' : 'b') : 'c') : 'd';

// 推荐:改用 if-else
let result;
if (condition1) {
  if (condition2) {
    result = condition3 ? 'a' : 'b';
  } else {
    result = 'c';
  }
} else {
  result = 'd';
}

嵌套三元表达式(谨慎使用)

let score = 85;
let grade = score >= 90 ? 'A' :
            score >= 80 ? 'B' :
            score >= 70 ? 'C' :
            score >= 60 ? 'D' : 'F';

console.log(grade); // B

// 更清晰的写法:使用 if-else 或查找表
function getGrade(score) {
  if (score >= 90) return 'A';
  if (score >= 80) return 'B';
  if (score >= 70) return 'C';
  if (score >= 60) return 'D';
  return 'F';
}

短路求值作为条件判断

利用逻辑运算符 &&|| 的短路特性,可以实现简洁的条件执行。

&& 实现条件执行

// 语法:condition && expression
// 当 condition 为真时,执行 expression;否则不执行

let isLoggedIn = true;
isLoggedIn && console.log('欢迎回来!'); // 会执行

isLoggedIn = false;
isLoggedIn && console.log('欢迎回来!'); // 不会执行

// 等价于:
if (isLoggedIn) {
  console.log('欢迎回来!');
}

|| 设置默认值

// 语法:value || defaultValue
// 当 value 为假值时,使用 defaultValue

function greet(name) {
  name = name || 'Guest';
  console.log('Hello, ' + name);
}

greet();        // Hello, Guest
greet('Alice'); // Hello, Alice

// 注意:|| 会把 0、'' 等假值也替换掉
function multiply(a, b) {
  a = a || 1;  // 如果 a 是 0,会被替换为 1!
  b = b || 1;
  return a * b;
}
console.log(multiply(0, 5)); // 5(错了!应该是 0)

// 更好的方式:使用 ??(空值合并运算符,ES2020)
function multiply2(a, b) {
  a = a ?? 1;  // 只对 null 和 undefined 使用默认值
  b = b ?? 1;
  return a * b;
}
console.log(multiply2(0, 5)); // 0(正确)

?? 空值合并运算符(ES2020)

// ?? 只对 null 和 undefined 返回默认值,其他假值保持不变
console.log(null ?? 'default');    // "default"
console.log(undefined ?? 'default'); // "default"
console.log(0 ?? 'default');      // 0(保持 0)
console.log('' ?? 'default');     // ""(保持空字符串)
console.log(false ?? 'default');  // false(保持 false)

综合示例

示例 1:成绩等级判断

function getGradeInfo(score) {
  if (score < 0 || score > 100) {
    return { grade: '无效', comment: '分数必须在 0-100 之间' };
  }

  let grade = score >= 90 ? 'A' :
              score >= 80 ? 'B' :
              score >= 70 ? 'C' :
              score >= 60 ? 'D' : 'F';

  let comment = score >= 60 ? '及格' : '不及格';

  return { grade, comment };
}

console.log(getGradeInfo(85)); // { grade: 'B', comment: '及格' }
console.log(getGradeInfo(55)); // { grade: 'F', comment: '不及格' }

示例 2:用户权限判断

function canAccess(user, resource) {
  // 未登录
  if (!user) return false;

  // 管理员有所有权限
  if (user.role === 'admin') return true;

  // 根据资源类型判断
  switch (resource.type) {
    case 'public':
      return true;
    case 'premium':
      return user.isPremium === true;
    case 'private':
      return user.id === resource.ownerId;
    default:
      return false;
  }
}

// 测试
let admin = { role: 'admin' };
let member = { role: 'user', isPremium: true };
let resource = { type: 'premium' };

console.log(canAccess(admin, resource));  // true
console.log(canAccess(member, resource)); // true
console.log(canAccess(null, resource));   // false

示例 3:表单验证

function validateForm(form) {
  let errors = [];

  // 用户名验证
  if (!form.username) {
    errors.push('用户名不能为空');
  } else if (form.username.length < 3) {
    errors.push('用户名至少 3 个字符');
  }

  // 邮箱验证(简单检查)
  let email = form.email;
  if (!email) {
    errors.push('邮箱不能为空');
  } else if (!email.includes('@')) {
    errors.push('邮箱格式不正确');
  }

  // 年龄验证
  let age = form.age;
  if (age == null) {  // 检查 null 和 undefined
    errors.push('年龄不能为空');
  } else if (age < 18) {
    errors.push('必须年满 18 岁');
  }

  // 返回结果
  return {
    isValid: errors.length === 0,
    errors: errors
  };
}

// 测试
let form = { username: 'ab', email: 'test', age: 16 };
let result = validateForm(form);
console.log(result.isValid); // false
console.log(result.errors);  // ["用户名至少 3 个字符", "邮箱格式不正确", "必须年满 18 岁"]

总结:如何选择

场景 推荐方式
简单的二选一赋值 三元表达式 ? :
多个互斥条件 if...else if...elseswitch
根据表达式值匹配 switch...case
简单的条件执行 && 短路求值
设置默认值 ??(ES2020)或 ||
复杂的条件逻辑 if...else(可读性更好)
多个 case 执行相同逻辑 switch 的 fall-through 或对象映射