alert([]==![])结果为true!求解释!

这个问题确实很奇怪,如下:

[] == false // true
![]         // false,既然[] == false,那么 !false 为什么是 false? 应该是true

接下来详细的说下这个问题:

1,[]==![] 是 [] == (![]) 也就是 obj 与 bool 对比。比较规则为:obj 调用 valueOf () 方法,其返回值与 bool 比较。比较中有bool值,将bool值转化为 0 或 1, ;字符串与数值比较,会将字符串先转化为数值。

2,如果两个操作数类型相同的话,使用(==)与(===)没有区别。全等比较除了在比较前转换类型之外,(==)与(===)没有区别,那么在两个类型相同的操作数比较时(==)与(===)没有区别;

基本上遵循这两点规则,进行说明,

[] == false ,由于需要调用对象的valueOf 方法,所以实际比较为: 
[].valueOf().toString() == false //true,由于 [].valueOf() 返回为对象,对象与bool比较,还会将对象在进行toString()转换。实际将[] 转为 "" 是 toSting()转换。
那么最重要的是知道 [] 不调用toString() ,本身到底是 真 还是 假。以最简单的方式验证:

alert(Boolean([])); //true
或下边的方式:
//1,弹出对话框,显示 1
if([]) {
    alert(1);
}
//2,弹出对话框,显示 1
if([] == false) {
    alert(1);
}
//3,报错:can't convert [] to primitive type
Array.prototype.toString = null;
if([] == false) {
    alert(1);
}
//4,弹出对话框,显示 1
Array.prototype.toString = null;
if([]) {
    alert(1);
}

那么经过这4步的验证,[] 实际为 真。

接下来就该验证 ![] 虽然没有比较,但是实际有没有调用toString() 或者 valueOf() .

Array.prototype.toString = function(){
    alert('called toString')
}
Array.prototype.valueOf = function(){
    alert('called valueOf');
}
if(![]){}; //没有输出called toString 和called valueOf,这里判断 !真

([]==![]) -> ([] == false) -> ([].toString()==false) -> (''==false) -> ('' == 0) -> (0 == 0) ->true

如果使用全等(===)的话,就不会出现这样的问题,因为不会转换类型后比较:

[]===![] // false

大概就是这样吧,可能有些地方说的不准确,大家帮完善吧。

posted @ 2014-06-27 11:40  Mrxia  阅读(563)  评论(0编辑  收藏  举报