重要的点
- 相等不一定全等,全等一定等于,很好理解
- 相等和不相等比较前会先转换操作数(强制转换,后面提到),全等和不全等则不会,所以这也是为什么使用全等运算符更安全的原因
相等的强制转换
- 嫌麻烦可以直接跳过,看后面的踩坑部分
- 强制转换不仅体现在相等运算符上,计算运算符也有,是个很复杂的点,此处不过多展开
规则
- 如果有一个操作数是布尔值,则转换为数值:
false => 0,true => 1
- 如果一个是字符串,另一个是数值,则字符串转换为数值
- 如果一个是对象,一个不是,则调用对象的
valueOf()
方法,用得到的基本类型按前面的规则比较 - 特殊规则:
null == undefined
- NaN不等于任何,包括它自己。可以这么理解,因为NaN的意思是 not a number,不是一个数,所以意味着它是不确定的,就像薛定谔的猫,在它确定之前它是没办法比较的,所以不相等
- 如果两个都是对象,则是比较地址的相同性
原理
- 在运算时,js会隐式调用 valueOf 和 toString 函数,这两函数是除 null 和 undefined 外其他数据类型原型链上共有的函数(意思就是其他类型都可以调用这两个函数)
- 前者:返回最适合该对象类型的原始值;后者:将该对象的原始值转换为字符串
- 一般,数值运算里,会优先调用前者;字符串运算里,会优先调用后者
- 想更深入理解可以查看这篇有意思的文章toString()和valueOf()区别
经典面试题
- 使
a == 1 && a == 2 && a == 3
为真,改写toString方法即可,valueOf同理
let a = {
i: 1,
// 定义类时可以重写toString/valueOf函数
toString: function () {
return a.i++
}
}
a == 1 && a == 2 && a == 3 // true
踩坑实战
1 正负零
0 === -0 // true
1 / +0 // Infinity
1 / -0 // -Infinity
- 0是有符号的,且正负零判定全等,但两者是不同的
- 想判断出正负零得这样
function a (a, b) {
if (a === b) return a !== 0 || 1 / a === 1 / b
return false
}
console.log(a(-0, 0))
2 字符串
's' == new String('') // false,类型不同
new String('s') == new String('s') // false,地址不同
1 == '1' // true,强制转换
- 如果用 new 创建number、string等,都是生成对象,比较地址
3 正则表达式
/1-9/ == /1-9/ // false,正则是对象,地址不同
'' + /1-9/ === '' + /1-9/ // 转换为字符串可比较内容是否相同(强制转换)
4 Date对象
let a = new Date()
let b = new Date()
+a === +b // true,加法使得a、b转换为数值(强制转换)
a.getTime() === b.getTime() // true
5 布尔值
var a = new Boolean('123');
var b = new Boolean('123');
+a === +b //true,同上理
6 NaN
// 自己和自己比较,不相等
NaN == NaN // flase
如果觉得对你有帮助的话,点个赞呗~
反正发文又不赚钱,交个朋友呗~
如需转载,请注明出处foolBirdd