你不知道的 JavaScript 系列中, 28 - && 和 ||

&& 和 || 运算符的返回值并不一定是布尔类型,而是两个操作数其中一个的值。

var a = 42;
var b = "abc";
var c = null;
a || b; // 42
c || b; // "abc"

a && b; // "abc"
c && b; // null

|| 和 && 首先会对第一个操作数(a 和 c)执行条件判断,如果其不是布尔值(如上例)就 先进行 ToBoolean 强制类型转换,然后再执行条件判断

对于 || 来说,如果条件判断结果为 true 就返回第一个操作数(a 和 c)的值,如果为 false 就返回第二个操作数(b)的值

&& 则相反,如果条件判断结果为 true 就返回第二个操作数(b)的值,如果为 false 就返回第一个操作数(a 和 c)的值

下面是一个十分常见的 || 的用法,也许你已经用过但并未完全理解:

function foo(a,b) {
  a = a || "hello";
  b = b || "world";
  console.log( a + " " + b );
}
foo(); // "hello world"
foo( "yeah", "yeah!" ); // "yeah yeah!"

a = a || "hello"(又称为 C# 的“空值合并运算符”的 JavaScript 版本)检查变量 a,如果还未赋值(或者为假值),就赋予它一个默认值("hello")

有一种用法对开发人员不常见,然而 JavaScript 代码压缩工具常用。就是如果第一个操作数为真值,则 && 运算符“选择”第二个操作数作为返回值,这也叫作“守护运算符”,即前面的表达式为后面的表达式“把关”:

function foo() {
  console.log( a );
}
var a = 42;
a && foo(); // 42

foo()只有在条件判断a通过时才会被调用。如果条件判断未通过,a && foo()就会悄然终止(也叫作“短路”,short circuiting),foo()不会被调用。

这样的用法对开发人员不太常见,开发人员通常使用if (a) { foo(); }。但JavaScript 代码压缩工具用的是a && foo(),因为更简洁。以后再碰到这样的代码你就知道是怎么回事了。

|| 和 && 各自有它们的用武之地,前提是我们理解并且愿意在代码中运用隐式强制类型 转换。