为什么 [ ]==false 是 true 而 !![ ] 是 true
今天写项目时判断一个数组为空,想节省时间判断数组是否为空用!arr来判断,结果为false
var a=[];
console.log(![])//false
明明[]是false为什么![ ]返回的是true
首先这是因为与 ECMA 规范和类型转换有关。
1.[]==false为什么是true,首先因为 == 号有强制转换功能,右边false先变为0,而接下来左边先会执行[].valueOf()返回本身还是[]
因为执行valueOf()不返回原始值(Number,String,Boolean,Underfined,Null),[]是个Object,是引用类型,所以还会执行[].toString()方法返回” “
,一个空字符串,最终空字符串在转换为0,所以[]==false,返回的是true。
2.这时候就有问题了,为什么会执行valueOf()和toString(),他们又是什么东西?
首先我们打印下Object的prototype
我们可以发现对象原型里有valueOf()和toString()这两个方法,数组也是对象所以说它也能调用这个方法。
那为什么会调用这个方法呢?
因为做比较运算时会运用一个比较算法如下图:
看上面的7,8,9,10就是我上面解析的步骤,那这个ToPrimitive()是什么?看下图
可以看出上面ToPrimitive()有两个参数,第一个是接受的参数就如一个空数组,第二个是期望类型(七大数据类型)
DefaultValue看上图,有点复杂。简单来说就是设置一个hint(期望类型),如果没有设置,默认期望类型就数字(Number)。除日期类型默认是字符串(String),所以一般来说就是期望类型是数字则先执行valueOf(),返回的不是原始值,则继续调用toString(),返回的是原始值则返回,如果还不是则抛出异常。反之期望值是字符串则相反。
为什么!![]==true,明白上面[为什么[ ]==false,就比较好理解了
因为!符号是会强制将值转换为Boolean,所以!![]可以写成!!(ToBoolean([])),下面是ToBoolean的转换规则
所以最终缩写为!!(true) 就等于true,这就是为什么判断数组为空不用![],还是根据数组长度来判断的好!