在我的代码中,我假设以下||
短路是安全的:
var $holidayExpandBarOrOpeningHours =
$(".expandBar + .holidayHours_c").prev() || $(".openingHours");
但令我惊讶的是,如果我们使用true语句短路空数组,仍然会返回一个空数组。我将使用下面的一些控制台代码进行演示,我的问题是为什么[] || true
评估为[]
。
false || "expected"
"expected"
false == []
true
[] || "expected"
[]
typeof([])
"object"
({}) || "expected"
Object {}
({}) == false
false
{} == false
SyntaxError: Unexpected token ==
我的一部分认为这是因为一个数组是object
,其评估结果为真,但是如果是这种情况而不是基于({}) == true
那么人们会期望[] == true
。
最后我要注意的是使用use 'strict'
模式时的结果是一样的。
答案 0 :(得分:6)
转换为布尔值时,[]
为真。
> !![]
true
> ![]
false
当转换为数字时,[]
为0.这就是为什么将它与false进行比较返回true:比较不同类型的两个值时,JavaScript首先将两者都转换为数字然后比较数字。
> +[]
0
> +false
0
> +[] == +false
true
答案 1 :(得分:4)
这是因为||
并使用==
不同的规则进行转换。
逻辑 - 或使用ToBoolean
,而平等等于使用ToNumber
/ ToPrimitive
。
来自11.11 Binary Logical Operators:
3)如果 ToBoolean(lval)为真,则返回lval。
由于ToBoolean([])
为真,[] || x
会产生[]
。这也是if([]) { /* this runs */ }
:JavaScript中的数组"truthy" values。
来自11.9.3 The Abstract Equality Comparison Algorithm:
7)如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)。
9)[..then]如果Type(x)是Object而Type(y)是String或Number, 返回比较结果 ToPrimitive(x) == y。
5)[..then]如果Type(x)是String而Type(y)是Number, 返回比较结果 ToNumber(x) == y。
应用于[] == true
的逻辑是ToNumber(ToPrimitive([])) == ToNumber(true)
。
转换值:
ToBoolean([])
是真的ToNumber(true)
是1 ToPrimitive([])
是空字符串(来自DefaultValue/toString
)所以:
ToNumber(ToPrimitive([])) == ToNumber(true)
ToNumber("") == 1
0 == 1
false
(约翰库格曼所说的话还有很长的路要走。)
此外,({}) == true
通常为 false ,并遵循与上述相同的转化次数。
在默认环境下,ToPrimtive({})
会根据Object.prototype.toString返回非空字符串(即"[object Object]"
)。此字符串将在ToNumber
之后评估为NaN,以便NaN == 1
;或者是假的。
有关ToPrimitive转换的详细信息,请参阅Why an empty Array type-converts to zero? +[]。
答案 2 :(得分:3)
空数组是一个对象;被强制为布尔值的物体是true
。所以
({}) || true; // -> {}
[] || true; // -> []
"" || true; // -> true (empty strings are coerced to false)
旁注 - 需要{}
周围的括号,以避免将其解析为块。