在2个空数组的松散相等比较中发生了什么

时间:2017-12-03 19:45:54

标签: javascript arrays coercion

我正在努力了解这个代码段如何在基本级别上运作

if([] == ![]){
console.log("this evaluates to true");
}

请帮助我理解我错在哪里。我的想法:

  1. 首先是运算符优先级,因此!==之前进行评估。
  2. 调用下一个ToPrimitive[]转换为空字符串。
  3. !运营商注意到它需要将""转换为boolean,因此它会将该值转换为false,然后否定为true。< / LI>
  4. ==更喜欢比较数字,所以在我的思考中true使1[]转换为""然后0
  5. 为什么它会起作用?我在哪里弄错了?

3 个答案:

答案 0 :(得分:12)

  

为什么它会起作用?

TLDR:

.Select(match => string.Concat(...))
.ToArray();

一些解释:

1)

  

首先有运算符优先级,因此[] == ![] //toBoolean [1] [] == !true [] == false //loose equality round one [2] //toPrimitive([]); toNumber(false) [3] "" == 0 //loose equality round two //toNumber("") [4] 0 === 0 true !

之前进行评估

Negating something首先将内部toBoolean方法调用到“某事”上。在这种情况下,这是一个Object(因为Arrays是Objects),为此它总是返回==,然后被否定。

2)

现在由loose equalities special behaviour决定(有关更多信息,请参阅金牛座答案):

  

如果A是对象(数组是对象)而B是布尔值,它将执行:

true

3)

ToPrimitive(A) == ToNumber(B)
  

ToPrimitive(A)尝试通过在A上调用A.toString和A.valueOf方法的不同序列,将其Object参数转换为原始值。

将数组转换为原语是通过调用 toPrimitive([]) (因为它们没有toString方法)完成的,基本上是valueOf

join(",")
  

如果参数为true,则结果为1。如果参数为false,则结果为+0。 Reference

因此toNumber(false) 转换为false

4)

+0
  

StringNumericLiteral为空或仅包含空格,将转换为+0。

所以最后toNumber("") 转换为""

  

我在哪里弄错了?

在第1步。否定某些内容不会调用+0,而是toPrimitive ...

答案 1 :(得分:5)

接受的答案不正确(不过现在是这样),请看这个例子:

if([5] == true) {
console.log("hello");	
}

如果确实按照接受的答案处理了所有内容,则[5] == true应该已评估为true,因为数组[5]将转换为其字符串副本"5" ),字符串"5"是真实的(Boolean("5") === truetrue),因此true == true必须为真。

但显然并非如此,因为条件不会评估为true

所以,实际发生的是:

  1。 ![]会将其操作数转换为布尔值,然后翻转该布尔值,每个对象都是真实的,因此![]将评估为false

此时,比较变为[] == false


  2。然后开始发挥作用的是这两条规则,#{3}}在#6中的抽象等效比较算法的规范中:

  
      
  1. 如果Type(x)是boolean,则返回比较结果ToNumber(x)== y。
  2.   
  3. 如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)
  4.   

此时,比较变为[] == 0


  3。然后,就是这条规则:

  

如果Type(x)是Object而Type(y)是String或Number,   返回比较结果ToPrimitive(x)== y。

正如@Jonas_W所述,数组的ToPrimitive将调用其toString,它将返回以逗号分隔的内容列表(我过于简单化)。

此时,比较变为"" == 0


  4。最后(好吧,差不多),这个规则:

  

如果Type(x)是String而Type(y)是Number,   返回比较结果ToNumber(x)== y。

转换为数字的空字符串为0Number("") == 0true)。

此时,比较变为0 == 0


  5. 最后,此规则适用:

  

如果Type(x)与Type(y)相同,那么      
.........
      如果Type(x)是Number,那么          
.........           如果x与y的Number值相同,则返回true。

而且,这就是比较评估为true的原因。您还可以将这些规则应用于我的第一个示例,以了解它未评估为true的原因。


我在上面引用的所有规则都在规范中明确说明clearly stated

答案 2 :(得分:0)

首先,要意识到您正在比较两种不同类型的值。 当你使用![]时会导致错误。你有代码(在核心它产生了这个):

if([] == false)

现在是第二部分:因为两个值都是不同的类型而你正在使用&#34; ==&#34;,javascript会将两种值类型转换为字符串(以确保它们具有相同的类型)。它从左边开始。 在左边我们有[]。所以javascript在[]上应用toString函数,结果为false。试试console.log([].toString())

你应该在左边作为字符串值得到假。在右边我们有布尔值false,而javascript对它做同样的事情。 它也在false上使用toString函数,这会导致字符串值为false。 试试console.log(false.toString())

这涉及两个核心概念:&#34; ==&#34; &#34; ==&#34;的作品和相关性operator - 无论是从左侧还是右侧开始。

关联性是指调用哪个运算符函数:从左到右或从右到左。 运营商喜欢==或!或+是使用前缀表示法的函数! 如果您使用&#34; ===&#34;,则上述if语句将导致false。 我希望有所帮助。