首先先把他们两两之间使用 == 比较的结果列出来:
undefined | null | 0 | [] | {} | NaN | '' | false | |
---|---|---|---|---|---|---|---|---|
undefined | true | true | false | false | false | false | false | false |
null | true | true | false | false | false | false | false | false |
0 | false | false | true | true | false | false | true | true |
[] | false | false | true | false | false | false | true | true |
{} | false | false | false | false | false | false | false | false |
NaN | false | false | false | false | false | false | false | false |
'' | false | false | true | true | false | false | true | true |
false | false | false | true | true | false | false | true | true |
要想知道为什么会出现这样的结果,我们首先要知道 == 的具体是什么样的:
== 的具体操作
- 如果x不是正常值(比如抛出一个错误),中断执行。
- 如果y不是正常值,中断执行。
- 如果Type(x)与Type(y)相同,执行严格相等运算x === y。
- 如果x是null,y是undefined,返回true。
- 如果x是undefined,y是null,返回true。
- 如果Type(x)是数值,Type(y)是字符串,返回x == ToNumber(y)的结果。
- 如果Type(x)是字符串,Type(y)是数值,返回ToNumber(x) == y的结果。
- 如果Type(x)是布尔值,返回ToNumber(x) == y的结果。
- 如果Type(y)是布尔值,返回x == ToNumber(y)的结果。
- 如果Type(x)是字符串或数值或Symbol值,Type(y)是对象,返回x == ToPrimitive(y)的结果。
- 如果Type(x)是对象,Type(y)是字符串或数值或Symbol值,返回ToPrimitive(x) == y的结果。
- 返回false。
然后我们来逐条分析结果:
undefined:根据第4、5步操作,undefined只有与 undefined 或 null 使用==比较时,结果才为 true。
null:同undefined。
0:当0与其他值比较时,根据第6步之后的操作,会先将字符串、对象、布尔值的值转换成数值再进行比较(undefined和null会直接进行到第12步,返回false)。
这些值转换成数值之后的值如下:
console.log(Number(undefined)); //NaN
console.log(Number(null)); //0
console.log(Number(0)); //0
console.log(Number([])); //0
console.log(Number({})); //NaN
console.log(Number(NaN)); //NaN
console.log(Number('')); //0
console.log(Number(false)); //0
[]:[]根据第10、11步操作,会将[]转换成数值后进行比较,[]转换成数值的值是0,所以结果同0(其中[]和[]比较时,会进入第三步操作,[]和[]都是对象,所以比较的是地址。这两个[]的地址不同,结果返回false)。
{}:{}根据第10、11步操作,会将{}转换成数值后进行比较,{}转换成数值后的值是NaN,但NaN和任何数都不相等,包括NaN自己,所以结果为全False。
console.log(NaN == NaN); //false
NaN:NaN是数值,会将其他转换成数值后与NaN比较,但NaN与任何数值比较都不相等,所以结果为全False。
‘’: 会将''转换成数值后与其他数比较,结果同 0。
false:同''。
如果直接使用if(var) 的形式来判断,判断的是变量转换成布尔值之后的结果是否为true而不是变量本身是否等于true。
console.log(Boolean(undefined)); //false
console.log(Boolean(null)); //false
console.log(Boolean(0)); //false
//注意这里 [] 和 {} 的结果都为 true
console.log(Boolean([])); //true
console.log(Boolean({})); //true
console.log(Boolean(NaN)); //false
console.log(Boolean('')); //false
console.log(Boolean(false)); //false
console.log(true == []); //false
console.log(true == {}); //false
怎么理解这个结果呢?
根据第8、9条规则,如果直接判断是否等于true,会先将true转换成数值:
console.log(Number(true)); //1
再将变量与true转换后的值(即1)进行比较。结果自然会是false。