Javascript中抽象相等比较算法

来源:互联网 发布:郑州关键词优化 编辑:程序博客网 时间:2024/06/14 23:19

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        //false2.如果Type(x)是Number,如果x或y为NaN,返回false,即:    NaN === NaN               //false   x与y数值相等或-0+0均返回true,否则返回false3.如果 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  能转化为数字为falseisNaN("abc")  //true   不能转换为数字为trueisNaN(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")              //truenew 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){…}语句中