原本是想简单写一下==和===之间的区别,后来看了下mdn发现了一些额外的相关知识,于是一并记录了下来
直接看MDN:JS中的相等性判断
JavaScript提供三种不同的值比较操作:
- 严格相等 ("triple equals" 或 "identity"),使用 === ,
- 宽松相等/抽象相等 ("double equals") ,使用 ==
- 以及
Object.is
(ECMAScript 2015/ ES6 新特性)
其区别在于,在用于判断两值是否相等时,若两值为数据类型不同,==会先转换数据类型再比较值,===不会进行类型转换(所以对于类型不同的值,===直接返回false),Object.is()与===类似,但对于NaN和-0,+0会进行特殊处理
NaN === NaN //false
-0 === +0 //true
Object.is(NaN, NaN) //true
Object.is(-0, +0) //false复制代码
综上,个人认为Object.is()在对待NaN的处理是符合直觉的,===在对待-0,+0的处理是符合直觉的
下面列一些零散的知识点
===效率比==高
因为===不涉及类型转换。个人认为应该尽量用===,要尽量避免==这种骚操作
x !== x ?
JS中只有NaN符合以上表达式
==的类型转换
相等操作符比较两个值是否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换), 最终的比较方式等同于全等操作符 === 的比较方式。 相等操作符满足交换律(即a == b和b == a是一样的)
- null和undefined和Number,String,Boolean做比较时自身不会进行类型转换,比较的另一方Number,String,Boolean也不会进行类型转换。即null,undefined和原始数据类型做比较时比较的双方都不会发生类型转换,所以均返回false,但与Object比较时会判断该对象是否是一个假值。
falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值
Boolean 上下文:需要将值转化为布尔值的场景,如条件语句和循环语句
印象中JS的对象都是真值,但其实存在一类十分不常见的可以转换为假值的对象,如document.all
document.all instanceof Object //true
typeof document.all //undefined
document.all == undefined //true复制代码
- Number在使用==做比较时具有最高的权重。这里的最高权重是我个人的理解。即五种原始数据类型中(不包括symbol),除undefined和null外(这两个大哥与任何类型的值做比较都不会自身都不会做类型转换)。剩下三种原始数据类型在做比较时遇到数据类型不一致时,非Number的数据类型都会使用Number() ?? 先转换为Number类型的值
1 == "1" ==> 1 == Number("1")
"1" == true ==> Number("1") == Number(true) //true
Number(true) //1
Number(false) //0复制代码
- Object在使用==做比较时权重最低。Object和Object做比较时,比较的是指针,不会进行数据类型转换。但如果Object和Number,String,Boolean比较,会调用toString或valueOf方法,将对象转换为原始值(Primitive),同时如果另外一个原始值不是Number,会使用Number将其转换为Number
[] == false //true
解析:
[].valueOf() ==> [],[].toString() ==> "" Number("") ==> 0
Number(false) ==> 0,0 == 0 ==> true
a = {}
a.toString() //"[object Object]"
b = {}
Object.prototype.toString = function() {return 0}
b == "" //true复制代码
总结:乍一看使用==做比较时类型转换的规则比较繁琐,但总结下来核心就三条
- null和undefined不会做任何数据类型转换
- 非Number的原始数据类型会先使用Number()将其转换为Number类型(null, undefined除外)
- Object和非Object类型的数据做比较时(null,undefined除外),会先使用toString或valueOf将其转换为原始数据类型(字符串类型)
但个人觉得实际工作中还是不要用 == 比较好,太JBSD
纠正:2019-5-19
发现自己之前写的有明显的错误,在此纠正。
之前认为Object类型和原始类型比较时,若另一运算子是字符串类型,会使用String方法转换对象。String方法转换对象的算法是先调用对象的toString方法,若返回不是原始类型,则再调用valueOf方法。若返回还不是原始类型,则报错。若另一运算子是数值或布尔类型,则会调用Number方法。Number方法也是调用valueOf和toString方法,只不过是先调用valueOf方法再调用toString方法