为什么[]==![] ?

190 阅读2分钟

多的不说,先上图。

上面两段代码虽然十分相似,可其原理却有着很大的区别。

先看第一段代码。

[]==[] //false

这个很好理解,引用类型之间比较时,比较的不是值,而是储存它们的地址。虽然两个空数组看上去一毛一样,可是它们并不是同一个数组,故为false。

第二段代码。

[]==![] //true

两段代码唯一的区别就是在第二个空数组前加了个取反符号,要知道,!的优先级是高于==的,所以在运行这段代码时,引擎先会给第二个数组进行取反操作,然后再与第一个数组比较。这就不是刚才简单的比较地址了,要理解这段代码,我们就要知道JS的隐式转换

取反操作会把数据类型变为Boolean再取反值,那么数组类型是怎么转换为Boolean类型呢?

根据转换规则,只有NaN,null,undefined,false,0,空字符串 转换为Boolean类型是false,其余都为true。所以Boolean([])的结果为true,再取反一下,我们可以知道第一次转换后的式子是[]==false

很明显,现在看不出结果,那接下来会怎么处理呢?

我们要记住一点,Boolean类型在参加比较时,会优先转换为Number类型。而引用类型在和基础类型比较时,会转化为基础类型。也就是,要把[]转化为Number类型。

大部分引用类型进行转换时,首先会调用valueOf()方法,如果其返回值是一个基本类型就将其作为转换结果,让我们来看看valueOf()的结果。

很遗憾,[].valueOf()的结果是[],是一个引用类型,不过丝毫不慌,虽然valueOf()方法扑街了,可是JS会在这之后调用toString()方法,将返回值作为转换结果。我们来看看。

我们可以看到toString()向我们返回了一个空字符串。这也就是[]的转换结果。可是一切都没有结束,别忘了我们的最终目的是转化为Number类型。

根据转换规则,空字符串转换为数字的结果为0,所以最终式子就是0==0,也就为true