【JS红宝书¹¹】布尔操作符

384 阅读5分钟

引子

本文讲述了 ECMA-262 中可用于操作数据值的操作符之布尔操作符

ECMAScript 中的操作符是独特的,因为它们可用于各种值,包括字符串、数值、布尔值,甚至还有对象;在应用给对象时,操作符通常会调用 valueOf()toString() 方法来取得可以计算的值。

布尔操作符

布尔操作符一共有 3 个:逻辑非(NOT)逻辑与(AND)和逻辑或(OR) ,它跟相等操作符几乎同样重要

逻辑非

逻辑非操作符由一个叹号(!)表示,可应用给 ECMAScript 中的任何值;这个操作符始终返回布尔值,无论应用到的是什么数据类型。

逻辑非操作符首先将操作数转换为布尔值,然后再对其取反;

逻辑非操作符规则:

  • 如果操作数是对象,则返回 false
  • 如果操作数是空字符串,则返回 false
  • 如果操作数是非空字符串,则返回 false
  • 如果操作数是数值 0,则返回 true
  • 如果操作数是 null ,则返回 true
  • 如果操作数是 NaN,则返回 true
  • 如果操作数是 undefined,则返回 true
代码演示
 console.log(!false); // true 
 console.log(!"blue"); // false 
 console.log(!0); // true 
 console.log(!NaN); // true 
 console.log(!""); // true 
 console.log(!12345); // false

取反操作

同时使用两个叹号(!!)也可以把任意值转换为布尔值,相当于调用了转型函数 Boolean()

无论操作数是什么类型,第一个叹号总会返回布尔值第二个叹号对该布尔值取反,从而给出变量真正对应的布尔值,结果与对同一个值使用 Boolean() 函数是一样的。

如下所示:

 console.log(!!"blue"); // true 
 console.log(!!0); // false 
 console.log(!!NaN); // false 
 console.log(!!""); // false 
 console.log(!!12345); // true

逻辑与

逻辑与操作符由两个和号(&&)表示,应用到两个值;

简单口诀:一个为false则都为false

它可用于任何类型的操作数,不限于布尔值

逻辑与操作符规则

如果有操作数不是布尔值,则逻辑与并不一定会返回布尔值,而是遵循如下规则:

  • 如果第一个操作数是对象,则返回第二个操作数
  • 如果第二个操作数是对象,则只有第一个操作数求值为 true 才会返回对象
  • 如果两个操作数是对象,则返回第二个操作数
  • 如果有一个操作数是 null ,则返回 null
  • 如果有一个操作数是 NaN,则返回 NaN
  • 如果有一个操作数是 undefined,则返回 undefined

短路特性

可以说逻辑与操作符是一种短路操作符,就是如果第一个操作数决定了结果,那么永远不会对第二个操作数求值;对逻辑与操作符来说,如果第一个操作数是 false,那么无论第二个操作数是什么值,结果也不可能等于 true。

来看下面这两个例子:

 let found = true; 
 let result = (found && test); // 报错
 console.log(result); // 不会执行
 ​
 /* 相反如果第一个为false则不会报错 */
 ​
 let found = false; 
 let result = (found && test); // 不会出错
 console.log(result); // 会执行

第一例子虽然 found为true 会执行检索下一个值 但是因为 test 没定义,所以报错,result也不会执行;第二个例子因为 found为false 所以不用再执行test了,直接把false 赋给result

注意: 在使用逻辑与操作符时,一定别忘了它的这个短路的特性

逻辑或

逻辑或操作符由两个管道符(||)表示,同样应用到两个值;

简单口诀:全都为 true 才返回 ture

与逻辑与类似,如果有一个操作数不是布尔值,那么逻辑或操作符也不一定返回布尔值。

逻辑或操作符规则

  • 如果第一个操作数是对象,则返回第一个操作数
  • 如果第一个操作数求值为false,则返回第二个操作数
  • 如果两个操作数都是对象,则返回第一个操作数
  • 如果两个操作数都是 null ,则返回 null
  • 如果两个操作数都是NaN,则返回 NaN
  • 如果两个操作数都是 undefined ,则返回 undefined

短路特性

同样与逻辑与类似,逻辑或操作符也具有短路的特性;只不过对逻辑或而言,第一个操作数求值为true,第二个操作数就不会再被求值了;

来看下面这几个例子:

 let found = true; 
 let result = (found || test); // 不会出错
 console.log(result); // 会执行
 ​
 /* 与逻辑或相反 o( ̄▽ ̄)d */
 ​
 let found = false;
 let result = (found || test); // 这里会出错
 console.log(result); // 不会执行这一行

第一例子中 found为true 会直接将值赋给result ,也不用再执行 test了;第二个例子虽然 found为false 但是逻辑与还会再检测下一个,发现 test 未定义,直接报错也不会执行 result

小知识

利用这个行为,可以避免给变量赋值 null 或 undefined;如下所示:

 let myObject = preferredObject || backupObject; 

在这个例子中,变量 myObject 会被赋予两个值中的一个;其中,preferredObject 变量包含首选的值,backupObject 变量包含备用的值;如果 preferredObject 不是 null,则它的值就会赋给myObject;如果 preferredObject 是 null,则 backupObject 的值就会赋给 myObject

PS: 这种模式在 ECMAScript 代码中经常用于变量赋值

总结

布尔操作符几乎在所有编程语言中都很重要,主要场景用于比较与校验

  • 逻辑非: 也称为取反操作符, 用于取反; !! 用于将值返回成布尔值再取反;
  • 逻辑与: && 如果一个为 false ,则都为 false
  • 逻辑或: || 如果都为 true ,才返回 true
  • 使用逻辑或对变量赋值可以校验是否为nullundefined