编辑: 引用已删除。与问题无关。
问题
为什么它总是(当一切都是真实的)取最后一个值?
例子 :
f= 1 && 2 && 3 //3
f= 'k' && 'd' && 's' //'s'
ps:我注意到在使用$.callbacks调查 pub/sub 时
编辑: 引用已删除。与问题无关。
问题
为什么它总是(当一切都是真实的)取最后一个值?
例子 :
f= 1 && 2 && 3 //3
f= 'k' && 'd' && 's' //'s'
ps:我注意到在使用$.callbacks调查 pub/sub 时
运算符&&
充当if 语句。仅当值为false时才会发生短路。否则,它会继续评估语句。
当你写a && b
它的意思是:a ? b : a
. 同样,a || b
意味着:a ? a : b
。
编辑:作者已经显着澄清了这个问题。
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中的定义类似。
那么它为什么总是(当一切都是真实的)取最后一个值?
因为如果前导值为真,它不能短路,因为它是一个“与”运算符,并且所有操作数都必须为真以满足条件。
在下面回复您的评论:
是的,但为什么它返回最后一个值?
因为它有用。:-) 在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.value
if bothobj
和obj.sub
are truthy 的值(例如,因为我们似乎将它们用作对象,所以它们是对象实例而不是null
or undefined
)。
||
做同样的事情:它返回它的第一个真值操作数。
&&
是一个逻辑运算符。这将测试一个值是真还是假。这篇链接的文章解释了虚假值等于undefined
、null
、NaN
、0
和。""
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
有一个值设置为一个非空的字符串。在第二个例子中,topic
is null 是假的。
因为如果第一个是真的,那么它应该继续检查第二个操作数直到最后一个。如果你愿意选择 1 || 2 || 3 相反,它将返回 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)
)。
短路评估和返回第二个表达式而不是布尔值是非常有用的功能。
运算符评估左操作数,如果它是真值,&&
则评估右操作数。类似地,||
运算符评估左操作数,如果它是假的,则评估右操作数。
这允许编写类似的东西
draw_element(color || "#F00");
具有使用的含义,color
除非未指定(例如color
is或) null
,并且在这种情况下使用默认值。undefined
""
你甚至可以使用类似的东西
draw_element(color || pick_new_color());
pick_new_color()
并且仅当未指定颜色时才会调用该函数。
一个非常常见的用法&&
是避免错误,例如:
if (x && x.constructor == Array) {
...
}
因为如果x
是null
或者undefined
你不能访问属性(如果你尝试会引发异常)。&&
如果返回第一个结果falsy
而不是仅仅返回第一个结果的事实false
确实不是那么有用。您的代码示例可以做到这一点,但这不是您在 Javascript 程序中经常会发现的。
回顾一下:&&
并且||
是短路的(即,如果在评估第一个操作数后结果已知,它们甚至不评估第二个操作数),这非常有用。它们还返回 falsy/truthy 值本身而不是 bool,这对||
(对 不太有用&&
)非常有用。