在JS中短路空数组有一个意想不到的结果:`[] || true == []`

时间:2013-12-18 21:32:14

标签: javascript

在我的代码中,我假设以下||短路是安全的:

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'模式时的结果是一样的。

3 个答案:

答案 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)

旁注 - 需要{}周围的括号,以避免将其解析为块。