布尔操作符

​ 对于编程语言来说,布尔操作符跟相等操作符几乎同样重要。如果没有能力测试两个值的关系,那么像 if-else 和循环这样的语句也没什么用了。布尔操作符一共有 3 个:逻辑非、逻辑与和逻辑或。

逻辑非

​ 逻辑非操作符由一个叹号(!)表示,可应用给 ECMAScript 中的任何值。这个操作符始终返回布尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转换为布尔值,然后再对其取反。换 句话说,逻辑非操作符会遵循如下规则。

- 如果操作数是对象,则返回 false。
- 如果操作数是空字符串,则返回 true。
- 如果操作数是非空字符串,则返回 false。
- 如果操作数是数值 0,则返回 true。
- 如果操作数是非 0 数值(包括 Infinity),则返回 false。
- 如果操作数是 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

逻辑与

​ 逻辑与操作符由两个和号(&&)表示,应用到两个值,如下所示:

let result = true && false;

​ 逻辑与操作符遵循如下真值表:

第一个操作数第二个操作数结 果
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

​ 逻辑与操作符可用于任何类型的操作数不限于布尔值。如果有操作数不是布尔值,则逻辑与并不一定会返回布尔值,而是遵循如下规则。

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

​ 逻辑与操作符是一种短路操作符,意思就是如果第一个操作数决定了结果,那么永远不会对第二个操作数求值。对逻辑与操作符来说,如果第一个操作数是 false,那么无论第二个操作数是什么值,结果也不可能等于 true。看下面的例子:

let found = true;
let result = (found && someUndeclaredVariable); // 这里会出错 
console.log(result); // 不会执行这一行

​ 上面的代码之所以会出错,是因为 someUndeclaredVariable 没有事先声明,所以当逻辑与操作符对它求值时就会报错。变量 found 的值是 true,逻辑与操作符会继续求值变量 someUndeclaredVariable。 但是由于 someUndeclaredVariable 没有定义,不能对它应用逻辑与操作符,因此就报错了。假如变量 found 的值是 false,那么就不会报错了:

let found = false;
let result = (found && someUndeclaredVariable); // 不会出错 
console.log(result); // 会执行

​ 这里,console.log 会成功执行。即使变量 someUndeclaredVariable 没有定义,由于第一个操作数是 false,逻辑与操作符也不会对它求值,因为此时对&&右边的操作数求值是没有意义的。在使用逻辑与操作符时,一定别忘了它的这个短路的特性

逻辑或

​ 逻辑或操作符由两个管道符(||)表示,比如:

let result = true || false;

​ 逻辑或操作符遵循如下真值表:

第一个操作数第二个操作数结 果
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

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

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

​ 同样与逻辑与类似,逻辑或操作符也具有短路的特性。只不过对逻辑或而言,第一个操作数求值为

true,第二个操作数就不会再被求值了。看下面的例子:

let found = true;
let result = (found || someUndeclaredVariable); // 不会出错 
console.log(result); // 会执行

​ 跟前面的例子一样,变量 someUndeclaredVariable 也没有定义。但是,因为变量 found 的值 为 true,所以逻辑或操作符不会对变量 someUndeclaredVariable 求值,而直接返回 true。假如把 found 的值改为 false,那就会报错了:

let found = false;
let result = (found || someUndeclaredVariable); // 这里会出错 
console.log(result); // 不会执行这一行

​ 利用这个行为,可以避免给变量赋值 null 或 undefined。比如:

let myObject = preferredObject || backupObject;

​ 在这个例子中,变量 myObject 会被赋予两个值中的一个。其中,preferredObject 变量包含首选的值,backupObject 变量包含备用的值。如果 preferredObject 不是 null,则它的值就会赋给 myObject;如果 preferredObject 是 null,则 backupObject 的值就会赋给 myObject。这种模 式在 ECMAScript 代码中经常用于变量赋值,本书后面的代码示例中也会经常用到。