一、非常规特殊情况
NaN !== NaN
+0 === -0
二、相等比较中的类型转换原则
字符串 —— 数字
Type(x) 左侧为数字,Type(y) 是字符串,x == y 则返回 x == ToNumber(y)
Type(y) 左侧为字符串,Type(x) 是数字,x == y 则返回 ToNumber(x) == y
小结:数字和字符串比较,则字符串变为数字。
其他类型 —— 布尔值
Type(x) 左侧为布尔类型,Type(y) 是其他类型,x == y 则返回 ToNumber(x) == y
Type(y) 右侧为布尔类型,Type(x) 是其他类型,x == y 则返回 x == ToNumber(y)
小结:布尔值和其他值比较,则布尔值变为数字。
注意:== 判定不等于 ToBoolean,所以==判定并不直接决定一个值为真值还是假值。
null —— undefined
在 == 比较中,null和undefined是一回事,可以互相转换。
对象 —— 非对象
Type(x) 左侧为基本类型,Type(y) 右侧为对象,x == y 则返回 x == ToPrimitive(y)
Type(x) 左侧为对象,Type(y) 右侧为基本类型,x == y 则返回 ToPrimitive(x) == y
小结:对象和基本类型比较,一律把对象ToPrimitive。
PS:相同类型比较时,对象和对象比较并不是判定值是否相等,而是判定是否为同一个引用,不需要类型转换。例如[] != [],{} != {}。
三、相等判定中的特殊情况
- 由于修改原生prototype中的valueOf导致的转换错误带来的特殊情况
- 七种false positive假真值,全部是由于类型转换时会转变成数字导致的
- “0” == false // 字符串和布尔值都会被转换类型变成数字,得到 0 == 0
- false == 0 // 同上
- false == “” // Number(“”) = 0
- false == [] // Number([]) = 0
- “” == 0
- “” == []
- 0 == []
- 极端情况
- [] == ![] // 左侧对象转换成数字0,右侧![]为布尔值false,同样转换成0
- 2 == [2] // ToPromitive([2]) = “2” 再作为String进行ToNumber得到2
- “” == [null] // ToPromitive([null]) = “”
- 0 == “\n” // “”、”\n”、” “等空字符串全部被ToNumber转换为0
四、ES5 – ToNumber 和 ToPrimitive 类型转换
- ToNumber —— 转换为数字
- undefined → NaN
- null → +0
- Boolean → true=1, false=0
- Number直接输出数字
- String → 同string转数字,从左到右解析,+-e0x等各自按照数字中的对应意义来解析(例:”0xA” → 10)
- Object → 先ToPrimitive再返回ToNumber
- 一切处理失败的情况 → NaN
- 对0开头的内容依然按照十进制处理
- ToPrimitive —— 转换为基本类型
- 未定义、空、布尔、数字、字符串,这些本来就是基本类型,直接返回不处理
- 对象:调用内部的defaultValue来检查是否含有valueOf方法
- 如果有valueOf且返回基本类型值,则直接返回
- 如果没有,用toString方法返回值来进行转换
- 如果两者都没有,返回TypeError
[CASE 1]:
var testValue = {
valueOf: function() { return "0xA" },
toString: function() { return "02" }
}
console.log(Number(testValue)) // 输出10,调用了valueOf且对"0xA"进行了toNumber变为十六进制的10
console.log(String(testValue)) // 输出"02",调用了toString直接输出
console.log(10 == testValue) // 输出 true,类型转换后值相等
console.log(10 === testValue) // 输出false,类型不同
// 如果toString返回的不是string,也不是简单值(数字、布尔、null),而是例如[2,4]等值,则调用valueOf返回,也就是返回"0xA"
[CASE 2]:
// case 2 参考<a href="http://www.cnblogs.com/ziyunfei/archive/2012/09/18/2691062.html">Converting a value to string in JavaScript</a>
var obj = {
valueOf: function () {
console.log("valueOf");
return {}; // 不是原始值,继续执行
},
toString: function () {
console.log("toString");
return {}; // 不是原始值,继续执行
}
};
console.log("" + obj);
// "valueof"
// "toString"
// Uncaught TypeError: Cannot convert object to primitive value