Javascript 为什么下面的说法是正确的;狗";==(“猫”、“狗”)

Javascript 为什么下面的说法是正确的;狗";==(“猫”、“狗”),javascript,Javascript,为什么&&运算符返回最后一个值(如果该语句为true) 为什么&&运算符返回最后一个值 因为它就是这样做的。在其他语言中,&运算符返回布尔值true或false。在Javascript中,它返回第一个或第二个操作数,因为这些值本身已经是“truthy”或“false” 因此,'Cat'和&&Dog'产生值'Dog',该值等于'Dog' 如果可以将expr1转换为false,则返回expr1;否则,返回expr2。因此,当与布尔值一起使用时,&&如果两者都使用,则返回true 操作数为真;否则,

为什么
&&
运算符返回最后一个值(如果该语句为true)

为什么&&运算符返回最后一个值

因为它就是这样做的。在其他语言中,
&
运算符返回布尔值
true
false
。在Javascript中,它返回第一个或第二个操作数,因为这些值本身已经是“truthy”或“false”

因此,
'Cat'和&&Dog'
产生值
'Dog'
,该值等于
'Dog'

如果可以将expr1转换为false,则返回expr1;否则,返回expr2。因此,当与布尔值一起使用时,&&如果两者都使用,则返回true 操作数为真;否则,返回false


对于表达式
“Cat”和“Dog”
,第一个表达式
“Cat”
不能转换为false或布尔值,因此它返回
“Dog”
,因为您询问了
true==(true和true)
。如果在布尔操作中使用非布尔值,javascript将转换为布尔值。非空字符串为“true”,因此它返回correct

我猜语言设计者希望使用户能够使用| |运算符作为“合并”运算符,例如“空合并”运算符??在C#中

换句话说,如果需要默认值,可以使用以下习惯用法:

var x = input || "default"; 
//x will be equal to input, unless input is falsey, 
//then x will be equal to "default"
这样想(基于来自

现在您可以看到
ToBool(“Cat”)
true
,因此
&
将给出
rhs
,它是
“Dog”
,然后
==
正在执行
“Dog”==“Dog”
,这意味着行给出
true


为完整起见,
|
运算符可以看作

// pseudo-JavaScript
function ||(lhs, rhs) { // lhs || rhs
    if (ToBool(lhs)) return lhs;
    return rhs;
}

因为这就是规范所说的。JavaScript的逻辑运算符不会将结果强制转换为布尔值。它们只返回一个操作数的值。当使用&&运算符时,必须计算条件的每一侧,因为
Dog
是最后一个条件,并且整个条件为true,因此返回Dog。我知道这个问题非常基本,但为什么要进行向下表决?从这样的规范来看,非空字符串是“true”,我情不自禁地想:“该死,那个实现看起来像个黑客。”。这是合乎逻辑的,不过…@Cerbrus我认为这是相当的天才,而不是黑客。既然已经有了在必要时基本上充当布尔值的值,为什么还要返回布尔值呢?这就允许更简洁的结构有时不会产生任何负面的副作用。@deceze:这正是为什么这样做是合乎逻辑的:PDo你经常以“因为它就是这样做的”?那么,还有什么其他答案呢?:)OP已经正确地识别了它是如何工作的,它是这样工作的,因为规范这么说的。@FrederikWordenskjold:Wild“因为规范上说,
&&
操作符就是这样做的。”更好吗?@Cerburs Yeah。这给了它一个实际的意义。否则,至少对我来说,这听起来像是作者故意不具建设性。我认为有一个专门讨论语义的堆栈交换网站。这个书面回答对我来说是非常有建设性的。如果你指的是标题示例,
“Dog”==“Cat”&“Dog”)
,它是在比较
“Dog”==“Dog”
<代码>(“猫”&“狗”)大致相当于
(!!“猫”?“狗”:“猫”)
。唯一涉及的布尔转换是条件,而不是结果。
function ToBool(x) {
    if (x !== undefined)
        if (x !== null)
            if (x !== false)
                if (x !== 0)
                    if (x === x) // not is NaN
                        if (x !== '')
                            return true;
    return false;
}

// pseudo-JavaScript
function &&(lhs, rhs) { // lhs && rhs
    if (ToBool(lhs)) return rhs;
    return lhs;
}
// pseudo-JavaScript
function ||(lhs, rhs) { // lhs || rhs
    if (ToBool(lhs)) return lhs;
    return rhs;
}