0

编辑: 引用已删除。与问题无关。

问题

为什么它总是(当一切都是真实的)取最后一个值?

例子 :

f= 1 && 2 && 3 //3

f= 'k' && 'd' && 's' //'s'

ps:我注意到在使用$.callbacks调查 pub/sub 时

在此处输入图像描述

4

7 回答 7

6

运算符&&充当if 语句仅当值为false时才会发生短路。否则,它会继续评估语句。

当你写a && b它的意思是:a ? b : a. 同样,a || b意味着:a ? a : b

于 2013-10-07T08:07:15.353 回答
4

编辑:作者已经显着澄清了这个问题。

JavaScript 逻辑 AND 运算符如果为假则返回左操作数,否则返回右操作数。让我们看一下逻辑真值表:

A     B     A && B
true  true  true
true  false false
false true  false
false false false

如您所见,如果 A 为假,我们可以返回它:

A     A && B
false false
false false

如果 A 不为假,我们可以返回 B:

B     A && B
true  true
false false

这是一个小的优化,当与弱类型一起使用时会导致有趣的副作用,例如 inline if:

var result = callback && callback()

// Generally equivalent to a simple if:
if (callback)
    result = callback();
else
    result = null;

还使用默认选项:

name = name || 'John';

// Generally equivalent to a simple if:
if (!name)
    name = 'John';

至于为什么会发生,好吧,因为这些运算符的定义与 ECMA-262中的定义类似。

于 2013-10-07T08:03:31.930 回答
3

那么它为什么总是(当一切都是真实的)取最后一个值?

因为如果前导值为真,它不能短路,因为它是一个“与”运算符,并且所有操作数都必须为真以满足条件。


在下面回复您的评论:

是的,但为什么它返回最后一个值?

因为它有用。:-) 在Netscape 的第一个 JavaScript版本true中,如果整个表达式为真则返回,false如果不是,则几乎立即他们意识到返回最终操作数会更有用。

例如,您可以这样做:

var value = obj && obj.value;

...这将设置value为假值(如果obj是假的)或obj.value(如果obj不是假的)。重要的是,如果是假的,它不会抛出错误obj。如果您不确定是否obj已设置,则非常方便守卫。您也不必停留在一个级别:

var value = obj && obj.sub && obj.sub.value;

value要么是假的,要么是obj.sub.valueif bothobjobj.subare truthy 的值(例如,因为我们似乎将它们用作对象,所以它们是对象实例而不是nullor undefined)。

||做同样的事情:它返回它的第一个真值操作数。

更多:JavaScript 非常强大的 OR 运算符 ( ||)

于 2013-10-07T08:03:39.587 回答
1

&&是一个逻辑运算符。这将测试一个值是还是。这篇链接的文章解释了虚假值等于undefinednullNaN0和。""false

从左到右检查逻辑表达式。如果表达式的任何部分被评估为 falsy,则表达式的其余部分将不被评估。在您的示例中,该值始终是真实的。在这里,我们可以分解您的第一个表达式:

f = 1 && 2 && 3;
f = 1 /* Okay, 1 is a truthy value, lets continue... */
f = 2 /* Still truthy, let's continue... */
f = 3 /* Still truthy, we've reached the end of the expression, f = 3. */

如果 3 之前的任何值是虚假的,则表达式将结束。为了在行动中展示这一点,只需将您的变量重新声明为:

f = 1 && 2 && 0 && 3;

这里 0 是一个假值(如上所述)。此处表达式的执行将在 0 处结束:

f = 1 /* Okay, 1 is a truthy value, lets continue... */
f = 2 /* Still truthy, let's continue... */
f = 0 /* Hey, this is falsy, lets stop here, f = 0. */
f = 3 /* We never get here as the expression has ended */

这里f最终为0。

在您的jQuery.Topic()示例中,&&用于确保id实际存在:

topic = id && topics[id]

我们可以用同样的方式分解:

/* Assume this is your topics array: */
topics = ["", "My First Topic", "My Second Topic"];

/* If we pass in the value 1 as "jQuery.Topic(1)": */
topic = id && topics[id]
topic = 1 /* This is truthy, let's continue... */
topic = topics[1] /* topics[1] === "My First Topic" */

/* Now lets assume we pass in nothing as "jQuery.Topic()": */
topic = id && topics[id]
topic = null /* This is falsy, let's stop here, topic = null. */

以下if陈述仅在真实情况下才topic有效。在第一个示例中,这种情况是因为topic有一个值设置为一个非空的字符串。在第二个例子中,topicis null 是假的。

于 2013-10-07T08:12:44.513 回答
1

因为如果第一个是真的,那么它应该继续检查第二个操作数直到最后一个。如果你愿意选择 1 || 2 || 3 相反,它将返回 1。

于 2013-10-07T08:13:59.383 回答
1

ECMAScript 标准规定12.11.2 运行时语义:评估

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression

1. Let lref be the result of evaluating LogicalANDExpression.
2. Let lval be GetValue(lref).
3. Let lbool be ToBoolean(lval).
4. ReturnIfAbrupt(lbool).
5. If lbool is false, return lval.
6. Let rref be the result of evaluating BitwiseORExpression.
7. Return GetValue(rref).

也就是说,首先我们检查第一个操作数是否被评估为“假”值(null, false, 0)。如果是,则返回第一个操作数。

但是,如果它是“真实的”,则对第二个操作数重复相同的过程,如果它被评估为真实值,则返回原始值 ( 7. Return GetValue(rref))。

于 2013-10-07T08:26:53.073 回答
0

短路评估和返回第二个表达式而不是布尔值是非常有用的功能。

运算符评估左操作数,如果它是真值,&&则评估右操作数。类似地,||运算符评估左操作数,如果它是假的,则评估右操作数。

这允许编写类似的东西

draw_element(color || "#F00");

具有使用的含义,color除非未指定(例如coloris或) null,并且在这种情况下使用默认值。undefined""

你甚至可以使用类似的东西

draw_element(color || pick_new_color());

pick_new_color()并且仅当未指定颜色时才会调用该函数。

一个非常常见的用法&&是避免错误,例如:

if (x && x.constructor == Array) {
    ...
}

因为如果xnull或者undefined你不能访问属性(如果你尝试会引发异常)。&&如果返回第一个结果falsy而不是仅仅返回第一个结果的事实false确实不是那么有用。您的代码示例可以做到这一点,但这不是您在 Javascript 程序中经常会发现的。

回顾一下:&&并且||是短路的(即,如果在评估第一个操作数后结果已知,它们甚至不评估第二个操作数),这非常有用。它们还返回 falsy/truthy 值本身而不是 bool,这对||(对 不太有用&&)非常有用。

于 2013-10-07T08:16:30.967 回答