Javascript中抽象相等比较算法

Javascript中的相等分为抽象相等和严格相等,其中抽象相等有点难以捉摸,笔试题中也经常遇到。对平时的开发而言,如果不是特别熟悉抽象相等,一般除

if(obj.a ==  null){
    //这里相当于obj.a === null || obj.a === undefined,简写形式
    //这是jquery源码中推荐的写法
}

外,建议用严格相等;

根据官方原文档 http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 :

一、抽象相等x==y的算法过程如下:
    1.Type(x)与Type(y)相同:
        如果Type(x)为Undefined或Null,则返回true,即:
           undefined==undefined;   //true 
           null==null              //true
        如果Type(x)为Number,如果x或y为NaN,返回false,即:
            NaN==NaN            //false
            x与y数值相等或-0与+0均返回true,否则返回false;
        如果Type(x)为String,则x和y对应位置的字符完全一样才返回true,否则返回false,
        如果Type(x)为Boolean,则相同值返回true,否则false
        如果Type(x)为Object,则相同引用返回true,否则false,看下面例子:
            var a={m:1}
            var b={m:1}
            a==b          //false
            结果为false,因为a,b不是相同引用,再看:
            var a={m:1}
            b=a
            a==b          //true
    2.Type(x)为Undefined,Type(y)为Null,返回true,即
            undefined==null   //true,
    3. Type(x)为String,Type(y)为Number,则将x转换为Number,然后再比较,例:
            1==“1//true
    4.Type(x)为Boolean,Type(y)为Number,则将x转换为Number再比较,true转化为1false转化为0,例
            true  == 1;    //true
            false == 0;    // true

    5.Type(x)为StringNumber,Type(y)为Object,则将y转换为基本值,例子:
            1   == new String("1")   //true
            "2" == new Number(2)     //true
            结果均为true

二、严格相等 ===

1.如果 Type(x) 与 Type(y) 的结果不一致,返回 false,即只要类型不一样,则返回false,例子:
     1         === "1"         //false
     undefined === null        //false
2.如果Type(x)是Number,如果x或y为NaN,返回false,即:
    NaN === NaN               //false
   x与y数值相等或-0+0均返回true,否则返回false
3.如果 Type(x) 结果为 Undefined,返回 true
  如果 Type(x) 结果为 Null,返回 true
  如果Type(x)为String,则x和y对应位置的字符完全一样才返回true,否则返回false
  如果Type(x)为Boolean,则相同值返回true,否则false
  如果Type(x)为Object,则相同引用返回true,否则false

总结:
严格等与抽象等的区别在于,严格等首先要求类型一样,在比较过程中不执行类型转换,抽象等对比较对象的类型会执行转换,再转换为同一类型后再进行值得比较。一些需要注意的点:

1、NaN 不与任何数相等,NaN不是一个确切的数,更像是一个范围。isNaN()是判断一个数能否转换为数字而不是判断一个数是不是NaN:

isNaN("123")  //false  能转化为数字为false
isNaN("abc")  //true   不能转换为数字为true
isNaN(NaN)    //true

2、0,+0,-0无论是在抽象相等还是在严格相等情况下都相等;
3、和0 相等(==) 字符:

"0"      ==  0
"00000"  ==  0
""       ==  0
" "      ==  0
"\n"     ==  0
"\t"     ==  0
"\f"     ==  0
...

,除字符数字之外,和0相等的只有false了。

4、undefined和null只与undefined和null==,再没有其他的情形;
5、Number与Boolean的比较,是把true转化为1,false转化为0再进行比较;
6、Object类型要通过引用是否相同判断,Object和String的比较是通过将Object转化为基本类型:

"ab"  == new String("ab")              //true
new String("ab")  == new String("ab")  //false

7、引用类型和基本类型的相等:

[2]      ==  2              //true
["abc"]  ==  "abc"          //true
[2,3]    ==  "2,3"          //true
["a","b","c"] == "a,b,c"    //true

这里涉及到ToPrimitive这个操作。
规范文档是这么讲的:

ToPrimitive是把引用类型转化为基本类型:
引用类型转换为字符串:
1.优先调用toString方法(如果有),看其返回结果是否是基本类型,如果是,转化为字符串,返回。
2.否则,调用valueOf方法(如果有),看其返回结果是否是基本类型,如果是,转化为字符串,返回。
3.其他报错。

引用类型转化为数字:
1.优先调用valueOf方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
2.否则,调用toString方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
3.其他报错。
文档规范具体如下(使用的是[[DefaultValue]]内部方法):
而在==中,是转化为数字的。
因为[2].valueOf()是[2]自己本身,不是基本类型,
尝试调用toString,结果是`"2"`,因此看"2"==2,因此是true。
那么[[[2]]] == 2呢?也是true的,这里就不验证了。
那么[2] == '2'时,虽然是与字符的比较,但是也是优先调用valueOf的。

我们可以验证一下:

var a = [2];
a.valueOf = function() {
return 3;
};
console.log(a == '3');

8、在Javascript逻辑运算中,0、”“、null、false、undefined、NaN都会判为false,其他都为true. 通常用在if(xx){…}语句中

你可能感兴趣的:(javascript,javascript,抽象数值相等)