JavaScript 布尔值与比较运算
程序最核心的能力是判断。密码对不对、年龄够不够、商品有没有库存,这些判断的结果只有两个,真或假。JavaScript 里用布尔值表示真假,这一篇讲布尔值、比较运算和逻辑运算,它们是条件判断的基石。
true 与 false
布尔值只有两个,true 表示真,false 表示假。
const isRain = true;
const isOpen = false;
console.log(typeof isRain); // 输出 boolean
布尔值通常不直接写死,而是通过比较运算算出来。把两个值放一起比较,结果就是布尔值。
比较运算符
比较运算符用于比较两个值,返回布尔值。包括大于、小于、大于等于、小于等于、严格相等、严格不等六种
console.log(5 > 3); // 输出 true
console.log(5 < 3); // 输出 false
console.log(5 >= 5); // 输出 true
console.log(5 <= 4); // 输出 false
console.log(5 === 5); // 输出 true,严格相等
console.log(5 !== 5); // 输出 false,严格不等
比较运算符可以用于数字,也可以用于字符串。字符串比较按字符顺序,比如 ‘a’ < ‘b’ 为 true,实际使用中字符串比较远没有数字频繁。
这里要强调一个关键原则,相等判断永远用 === 和 !==,本教程不会出现 == 和 !=。
为什么不用 ==,一律用 ===
== 和 != 会做类型转换,比较前先把两边的值转成相同类型再比较,行为往往出人意料
console.log(5 == '5'); // 输出 true,数字和字符串被当成相等
console.log(true == 1); // 输出 true,布尔值被当成数字比较
console.log(0 == ''); // 输出 true,空字符串和 0 相等
三个例子都不符合直觉。5 和 ‘5’ 一个是数字一个是字符串,怎么就相等了。转换规则复杂且难以记忆,很容易埋下隐蔽的 bug。为什么会有这样的规则,涉及类型转换原理,本教程不深究,只需记住结论,== 的规则让你踩坑,=== 的规则一目了然。
=== 严格相等要求类型和值都相等,没有隐式转换
console.log(5 === '5'); // 输出 false,类型不同
console.log(true === 1); // 输出 false,类型不同
console.log(5 === 5); // 输出 true,类型和值都相等
结论只有一句,相等比较一律用 === 和 !==。
逻辑运算符
逻辑运算符用于组合多个比较条件,包括 &&(与)、||(或)、!(非)三种。
- && 与,两边都为 true 结果为 true。
- || 或,只要一边为 true 结果为 true。
- ! 非,取反,true 变 false,false 变 true。
const age = 20;
const hasTicket = true;
console.log(age >= 18 && hasTicket); // 输出 true,成年且持票
console.log(age >= 18 && !hasTicket); // 输出 false
console.log(age < 18 || hasTicket); // 输出 true,未成年或持票
console.log(!hasTicket); // 输出 false,取反
组合条件的可读性有个技巧,把表达式读成自然语言,age >= 18 && hasTicket 读作”年龄满 18 且持票”,逻辑立刻清晰。
短路求值
&& 和 || 有个特性叫短路求值,条件够早确定结果时,右侧表达式根本不会执行。
- && 左边为假,整个结果已定为假,右边不执行。
- || 左边为真,整个结果已定为真,右边不执行。
false && console.log('不执行');
true || console.log('不执行');
短路求值常常被用来写紧凑的防御代码,比如用户对象可能不存在时,user && user.name 直接拿到名字或 undefined,不会报错。新手阶段先知道有这回事,实际用到时候自然熟。
小结
- 布尔值只有 true 和 false,比较运算的结果就是布尔值。
- 比较运算符包括 > < >= <= === !==,相等比较永远用 === 和 !==。
- == 和 != 会做类型转换,5 == ‘5’ 和 true == 1 都是 true,行为难以预料,不要使用。
- && 与、|| 或、! 非,用于组合多个比较条件。
- 短路求值,&& 左边为假或 || 左边为真时,右边表达式不执行。