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转化为1,false转化为0,例
true == 1; //true
false == 0; // true
5.Type(x)为String或Number,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){…}语句中