JavaScript && 及 || 操作

JavaScript && 及 || 操作

和类C语言一样,JavaScript定义 && 及 || 分别表示逻辑与、或操作。使用true和false两个布尔值可生成下列真值表:

// Logical AND operation
true  && true;  // true
true  && false; // false
false && true;  // false
false && false; // false

// Logical OR operation
true  || true;  // true
true  || false; // true
false || true;  // true
false || false; // false

对于与操作,只有两者都为true才返回true,其他情况返回false;而或操作,仅两者都为false才返回false,其他期刊返回true。

1. 对非布尔值使用逻辑操作

在JavaScript中逻辑操作与类C语言语义不同,可以对任何类型表达式执行逻辑操作,不仅仅局限于布尔类型,而且逻辑操作不总是返回布尔值,请参加规范说明:

The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.

下面示例显示布尔操作结果情况:

"foo" && "bar"; // "bar"
"bar" && "foo"; // "foo"
"foo" && "";    // ""
""    && "foo"; // ""

"foo" || "bar"; // "foo"
"bar" || "foo"; // "bar"
"foo" || "";    // "foo"
""    || "foo"; // "foo"

&& 、|| 的结果恰为两个操作表示式其中之一。

  • A && B 如果A能强制转为false则返回A,否则返回B.
  • A || B 如果A能强制转为true则返回A,否则返回B.

其结果总是两操作表达式其中之一,如 Kyle Simpson 《You Don’t Know JS》描述:

In fact, I would argue these operators shouldn’t even be called “logical operators”, as that name is incomplete in describing what they do. If I were to give them a more accurate (if more clumsy) name, I’d call them “selector operators,” or more completely, “operand selector operators.”

2. 控制流结构即真值

实际上我们可能没有注意到 && 及 || 并不总是返回布尔值。像if表达式或循环结构只有当评估条件为真时才会执行结构体语句,但并不是非要布尔值:

let values = [1, 2, 3];

while (values.length) {
  console.log(values.pop());
}

// 3
// 2
// 1

那么什么样的表达式被认为是真值呢?在JavaScript中所有值都被认为真值,除了下面六个假值:

  • false
  • undefined
  • null
  • NaN
  • 0 (both +0 and -0)
  • “”

上面while循环中,当最后一个元素删除后,values.length返回0即假值。因此循环体不再执行并终止。

3. 函数返回值

现在看一个示例,&&和||并不一定产生一个布尔值。web应用中,用户可以登出,此时user对象为null,或者登录后user对象存在并包括一个isAdmin属性。

如果需要检查当前用户是否为管理员,首先需要检查user是否已认证(即user不为null),然后访问isAdmin属性是否为真:

let user = { isAdmin: true };

// ...

if (user && user.isAdmin) {
  // ...
}

你可能会想抽取user && user.isAdmin表示式至单独isAdministrator函数中,可以在多个地方重复使用:

function isAdministrator(user) {
  return user && user.isAdmin;
}

let user = { isAdmin: true };

if (isAdministrator(user)) {
  // ...
}

user对象包括isAdmin属性,无论true和false返回结果和预期的一样:

isAdministrator({ isAdmin: true }); // true
isAdministrator({ isAdmin: false }); // false

但user对象为null会发生什么?

isAdministrator(null); // null

user && user.isAdmin表达式的结果为null,即第一个操作表达式被返回,因为user为空被视为false。isAdministrator函数应该仅返回布尔值,就如名称is所表明的,但结果却包括null。

4. 强制转换为布尔值

在JavaScript中,常用的强制转换任何类型值为布尔值是使用逻辑取反操作两次:

function isAdministrator(user) {
    return !!(user && user.isAdmin);
}

如果单个操作数可强制转成true,那么!操作返回false;否则返回true。其结果总是布尔值,但操作数的值被反转,因此应用两次!操作:

!!true = !false = true
!!false = !true = false

!!0 = !true = false
!!1 = !false = true

另外一种方法使用Boolean函数,其可以更加清晰转换给定值为布尔类型:

function isAdministrator(user) {
    return Boolean(user && user.isAdmin);
}

5. 总结

JavaScript中 && 、 || 并不总是返回布尔值,两者总是返回其中一个操作数。使用两个!!或Boolean函数可以正确返回布尔类型。

发布了395 篇原创文章 · 获赞 761 · 访问量 143万+

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/104106946