09.JavaScript 比较运算符与逻辑运算符
📋 速查对照表
比较运算符
| 运算符 | 名称 | 描述 | 示例 | 结果 |
|---|---|---|---|---|
== |
等于 | 值相等就返回 true | 5 == "5" |
true |
=== |
严格等于 | 值和类型都相等才返回 true | 5 === "5" |
false |
!= |
不等于 | 值不相等就返回 true | 5 != "5" |
false |
!== |
严格不等于 | 值或类型不相等就返回 true | 5 !== "5" |
true |
> |
大于 | 左边大于右边返回 true | 10 > 5 |
true |
< |
小于 | 左边小于右边返回 true | 10 < 5 |
false |
>= |
大于等于 | 左边大于或等于右边返回 true | 5 >= 5 |
true |
<= |
小于等于 | 左边小于或等于右边返回 true | 5 <= 3 |
false |
逻辑运算符
| 运算符 | 名称 | 描述 | 示例 | 结果 |
|---|---|---|---|---|
&& |
逻辑与 | 两边都为 true 才返回 true | true && false |
false |
|| |
逻辑或 | 至少一边为 true 就返回 true | true || false |
true |
! |
逻辑非 | 把 true 变 false,false 变 true | !true |
false |
?? |
空值合并 | 左边是 null/undefined 就返回右边 | null ?? "默认" |
"默认" |
?. |
可选链 | 安全地访问对象属性 | user?.name |
不会报错 |
一、比较运算符
1. == 等于(宽松相等)
比较值是否相等,如果类型不同会自动转换类型再比较。
console.log(5 == 5); // true
console.log(5 == "5"); // true(字符串"5"转成数字5)
console.log(true == 1); // true(true转成1)
console.log(false == 0); // true(false转成0)
console.log(null == undefined); // true
2. === 严格等于(推荐使用)
值和类型都必须相等。
console.log(5 === 5); // true
console.log(5 === "5"); // false(类型不同)
console.log(true === 1); // false(类型不同)
console.log(false === 0); // false(类型不同)
console.log(null === undefined); // false(类型不同)
3. != 不等于(宽松)
console.log(5 != 3); // true(值不相等)
console.log(5 != "5"); // false(值相等)
console.log(true != 1); // false(值相等)
4. !== 严格不等于(推荐使用)
console.log(5 !== 3); // true
console.log(5 !== "5"); // true(类型不同)
console.log(true !== 1); // true(类型不同)
5. > 大于
console.log(10 > 5); // true
console.log(5 > 10); // false
console.log("10" > "5"); // true(字符串比较第一个字符)
console.log("abc" > "abd"); // false(逐字符比较,'c' < 'd')
6. < 小于
console.log(5 < 10); // true
console.log(10 < 5); // false
console.log("apple" < "banana"); // true(a在b前面)
7. >= 大于等于
console.log(5 >= 5); // true(等于)
console.log(10 >= 5); // true(大于)
console.log(3 >= 5); // false
8. <= 小于等于
console.log(5 <= 5); // true(等于)
console.log(3 <= 5); // true(小于)
console.log(10 <= 5); // false
二、逻辑运算符
1. && 逻辑与(AND)
// 两个条件都为 true,结果才是 true
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false
// 实际应用:检查多个条件
let age = 25;
let hasLicense = true;
if (age >= 18 && hasLicense) {
console.log("可以开车"); // 执行
}
// 短路特性:如果第一个为 false,就不会看第二个
let x = 0;
console.log(false && (x++)); // false(x++不会执行)
console.log(x); // 0(x没有增加)
2. || 逻辑或(OR)
// 至少一个条件为 true,结果就是 true
console.log(true || true); // true
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false
// 实际应用:提供默认值
let username = "";
let displayName = username || "游客";
console.log(displayName); // "游客"
// 短路特性:如果第一个为 true,就不会看第二个
let y = 0;
console.log(true || (y++)); // true(y++不会执行)
console.log(y); // 0(y没有增加)
3. ! 逻辑非(NOT)
// 取反:true 变 false,false 变 true
console.log(!true); // false
console.log(!false); // true
console.log(!0); // true(0转成false,再取反)
console.log(!"hello"); // false(非空字符串转成true,再取反)
// 双重否定:转成布尔值
console.log(!!5); // true
console.log(!!0); // false
console.log(!!""); // false
4. ?? 空值合并运算符(ES2020)
// 只有左边是 null 或 undefined 时才返回右边
console.log(null ?? "默认值"); // "默认值"
console.log(undefined ?? "默认值"); // "默认值"
console.log(0 ?? "默认值"); // 0(不是null/undefined)
console.log("" ?? "默认值"); // ""(不是null/undefined)
console.log(false ?? "默认值"); // false(不是null/undefined)
// 与 || 的区别
console.log(0 || "默认"); // "默认"(0被当作false)
console.log(0 ?? "默认"); // 0(0不是null/undefined)
console.log("" || "默认"); // "默认"(空字符串被当作false)
console.log("" ?? "默认"); // ""(空字符串不是null/undefined)
5. ?. 可选链运算符(ES2020)
// 安全地访问嵌套对象属性
let user = {
name: "张三",
address: {
city: "北京"
}
};
// 传统写法(繁琐)
let city1 = user && user.address && user.address.city;
// 可选链写法(简洁)
let city2 = user?.address?.city;
console.log(city2); // "北京"
// 如果属性不存在,返回undefined而不是报错
console.log(user?.contact?.phone); // undefined(不会报错)
// 也可以用于方法调用
let obj = {
greet: function() { return "Hello"; }
};
console.log(obj.greet?.()); // "Hello"
console.log(obj.sayHi?.()); // undefined(不会报错)
三、特殊比较规则
1. NaN 的特殊性
// NaN 不等于任何值,包括它自己
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
// 使用 isNaN() 或 Number.isNaN() 判断
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("abc")); // false(传统isNaN会返回true)
2. null 和 undefined 的比较
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(null == 0); // false
console.log(undefined == 0); // false
3. 字符串和数字比较
// 字符串会先转成数字再比较
console.log("5" == 5); // true
console.log("5" === 5); // false
console.log("10" > "5"); // true(比较第一个字符"1" > "5"?不,这里比较数值)
console.log("10" > 5); // true(字符串"10"转成数字10)
// 注意:如果字符串不能转成数字,会变成NaN
console.log("abc" > 5); // false("abc"转成NaN,NaN与任何比较都是false)
四、组合使用示例
1. 复杂条件判断
let age = 25;
let hasLicense = true;
let hasCar = false;
// 可以开车去上班的条件
let canDriveToWork = age >= 18 && hasLicense && hasCar;
console.log(canDriveToWork); // false(没有车)
// 可以学车的条件
let canLearnDrive = age >= 18 && !hasLicense;
console.log(canLearnDrive); // false(已经有驾照了)
// 打折条件:学生或老年人
let isStudent = true;
let isSenior = false;
let discount = isStudent || isSenior;
console.log(discount); // true
2. 表单验证
function validateForm(username, password, email) {
// 所有条件都必须满足
let isValid =
username.length >= 3 && // 用户名至少3位
password.length >= 6 && // 密码至少6位
email.includes("@") && // 邮箱必须包含@
email.includes("."); // 邮箱必须包含.
return isValid;
}
console.log(validateForm("张三", "123456", "test@qq.com")); // true
3. 权限检查
let user = {
isAdmin: false,
isVIP: true,
credits: 100
};
// VIP用户或管理员可以访问
let canAccess = user.isAdmin || user.isVIP;
console.log(canAccess); // true
// 有足够积分且不是管理员(防止管理员刷分)
let canBuy = user.credits >= 50 && !user.isAdmin;
console.log(canBuy); // true
五、运算符优先级
优先级从高到低
// 1. 小括号 () - 最高优先级
// 2. 逻辑非 !
// 3. 比较运算符 >, <, >=, <=, ==, !=, ===, !==
// 4. 逻辑与 &&
// 5. 逻辑或 ||
// 6. 空值合并 ??
使用括号明确优先级
// 混淆的表达式
let result1 = true || false && false;
console.log(result1); // true(&&优先级高于||,先算false&&false=false,再算true||false=true)
// 使用括号明确意图
let result2 = (true || false) && false;
console.log(result2); // false(先算true||false=true,再算true&&false=false)
// 推荐的写法:复杂表达式加括号
let age = 20;
let isStudent = true;
let hasDiscount = (age < 18 || age >= 65) && isStudent;
六、短路运算的实际应用
1. 条件执行
let isLoggedIn = true;
// 如果用户已登录,才执行函数
isLoggedIn && console.log("显示用户菜单");
// 相当于:
if (isLoggedIn) {
console.log("显示用户菜单");
}
2. 设置默认值
function greet(name) {
// 如果name不存在,使用默认值
name = name || "朋友";
console.log(`你好,${name}!`);
}
greet("张三"); // "你好,张三!"
greet(); // "你好,朋友!"
// 更好的写法(ES2020):
function greetBetter(name) {
name = name ?? "朋友";
console.log(`你好,${name}!`);
}
3. 链式调用保护
// 传统写法
function getCity(user) {
if (user && user.address && user.address.city) {
return user.address.city;
}
return "未知";
}
// 使用可选链(简洁)
function getCityModern(user) {
return user?.address?.city ?? "未知";
}
七、常见错误与注意事项
1. 使用 === 而不是 ==
// ❌ 容易出现意外结果
console.log(0 == false); // true(可能不是想要的结果)
console.log("" == false); // true
console.log([] == false); // true
// ✅ 使用严格比较
console.log(0 === false); // false(更清晰)
console.log("" === false); // false
console.log([] === false); // false
2. 注意浮点数精度
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// 解决方法:设置误差范围
function floatEqual(a, b) {
return Math.abs(a - b) < 0.000001;
}
console.log(floatEqual(0.1 + 0.2, 0.3)); // true
3. 理解短路特性
let count = 0;
// ❌ 可能达不到预期效果
function increment() {
return count++;
}
// 因为短路,increment()不会执行
console.log(false && increment());
console.log(count); // 0(没有增加)
// ✅ 明确想要的效果
if (false) {
increment();
}
4. 避免过度嵌套
// ❌ 难以阅读
if (user && user.profile && user.profile.settings && user.profile.settings.theme === "dark") {
// ...
}
// ✅ 使用可选链
if (user?.profile?.settings?.theme === "dark") {
// ...
}
// ✅ 或者提取变量
const theme = user?.profile?.settings?.theme;
if (theme === "dark") {
// ...
}
八、练习题
练习1:判断成绩等级
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";
}
console.log(getGrade(85)); // "B"
console.log(getGrade(55)); // "F"
练习2:检查用户名合法性
function isValidUsername(username) {
// 要求:长度3-10,只能包含字母和数字
const minLength = 3;
const maxLength = 10;
const regex = /^[A-Za-z0-9]+$/;
return username.length >= minLength &&
username.length <= maxLength &&
regex.test(username);
}
console.log(isValidUsername("abc123")); // true
console.log(isValidUsername("ab")); // false(太短)
console.log(isValidUsername("abc123!@#")); // false(有特殊字符)
练习3:三元运算符(条件运算符)
// 语法:条件 ? 值1 : 值2
let age = 20;
let status = age >= 18 ? "成人" : "未成年";
console.log(status); // "成人"
// 嵌套三元运算符(不建议,可读性差)
let score = 85;
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" :
score >= 60 ? "D" : "F";
console.log(grade); // "B"
九、总结口诀
比较运算符比大小,==宽松===严格。
!=宽松!==严格,>大于<小于。
>=小于等于,<=大于等于。
逻辑运算符有三个,&&与、||或、!非。
&&两边真才真,||一边真就真。
!是取反真变假,短路特性效率高。
??空值合并运算符,null/undefined用默认。
?.可选链运算符,安全访问不报错。
记住优先级,复杂加括号。
多用严格等,避免类型转换坑。
最佳实践建议
- 始终使用
===和!== - 利用短路特性简化代码
- 使用可选链
?.避免属性访问错误 - 使用空值合并
??设置默认值 - 复杂表达式用括号明确优先级
- 避免深度嵌套,提取变量提高可读性
掌握了比较和逻辑运算符,你就有了JavaScript中最重要的决策工具!🎯







