[] == false,和!![] == false结果为什么不一样?探究 == 本质

时间:2023-01-19 19:33:52

<script>
console.log([] == false, !![] == false);// true false
console.log([] === false, !![] === false);// false false
console.log([] == []);// false
var a = [];
console.log(a == !!a);//fasle
</script>



先解析[] == false为什么是true?

 

他是经历了这个过程最终才为true的。

[] == false)   ---->  ([] === +0)   ---->  (“”== +0)  ---->  (+0 == +0)  --->   true

 别惊讶,下面我慢慢来分析。


<hr/>

当js引擎解析到[] == false 的时候,会解析执行左右表达式,并分别取出执行结果的值,上述分别为数组对象和false。然后将数组设置为x,false设置为y执行下面的这个

抽象比较算法

 [] == false,和!![] == false结果为什么不一样?探究 == 本质

在执行抽象相等比较算法的过程中,会发现会将xy操作数进行隐式类型转化的,这也是==运算符副作用的体现。

 

对于 [] == false的问题应该关注上述步骤的78910步骤。

因为[]和false不是同一类型,所以执行到8的时候会将false调用toNumber()内部方法转化成数字,然后在执行抽象相等比较算法。

toNumber()会将false转化成+0.

 

<hr/>

然后将[] == +0.继续进行比较算法,执行到10 之后开始使用toPrimitive( )对[]进行转化。

ToPrimitive()转化方法如下:

ToPrimitive()

[] == false,和!![] == false结果为什么不一样?探究 == 本质

 

 

toPrimitive方法的目的就是将输入的参数转化成非对象类型。

对于任何的对象,比如[]讲调用自身的DefaultValue内部方法,同时可以传入一个期望的类型,一般是数组或者字符串,在 - ++ -- 等运算符为数字 而+ 可能为字符串。但是这里==没有明确期望的类型。所以在DefaultValue中会做相应的处理。



<hr/>

DefaultValue处理过程:

 [] == false,和!![] == false结果为什么不一样?探究 == 本质

先不着急判断[].DefaultValue值是什么,先解读一下这个算法。

如果期望类型hint为字符串,那么:

先调用备操作对象的toString方法,[get]方式获得,所以会在原型链中查找,如果找到,是一个可以调用的被定义的方法的话,则将对象作为this调用这个方法。否则如果得到值为原始值,则直接返回。

为什么这里要多一步的到值是否可调用判断呢?因为toSTring实在原型链中查找的,所以可以通过对对象的构造函数的prototype属性重写tostring方法得到想要的效果。

如果没有得到原始值,则再调用valueOf方法过程和toString一样,最终如果都不是原始值,则抛出异常。

如果期望类型为数字类型,则先调用valueOf后调用toString。

最重要的是,如果没有明确知道期望类型的话,除非是Data类型默认期望为字符串。其他对象默认为数字处理,也就是说先调用valueOf方法后调用toString方法。

所以,[] 也就明白了实现调用这个数组的valueOf方法如果不是返回原始类型,则调用toString方法。

 

<hr/>

[]继承了Array的prototype方法,所以执行的是Array.prototype.valueOf( ),但是Array很遗憾的是没有实现valueOf方法,所以很遗憾,根据原型链,最终调用Object.prototype.valueOf

方法。

但是Object.prototype.valueOf返回的是一个对象。不是原始类型还是继续调用Array.prototype.toString()方法。

 Array.prototype.toString()

[] == false,和!![] == false结果为什么不一样?探究 == 本质

所以他应该调用join方法的,没有传入参数的情况下,返回的是使用,分割的分别调用每一个元素toString的字符串拼接,因为[]中没有元素所以返回的应该是空的字符串。

所以最终变成了”” == 0;

 

根据抽象比较算法45会将空字符串调用toNumber方法转化成数字 ,最终变成这样 +0 == +0;

然后再调用抽象比较算法。+0和+0是同一类型都是数字,并且有-0和+0相等所以 最终返回true.

 

 

对于为什么  [] == []为false,!![] == false为false可以试着根据上述过程进行进一步的分析。