JavaScript 中「相等运算符」和「严格相等运算符」的规则和关系
引言
首先我们抛出两个问题:
为什么
[1] == [1]
为false
?为什么
[1] == 1
为true
?
知识点
如果我们要解决上面的疑问,就需要先搞懂 ==
和 ===
的规则和关系
===
判断规则:
如果 类型 不同,就 不相等
如果两个值都是 数值
,并且是同一个值,那么 相等
( !
例外)
如果两个值都是 字符串
,每个位置的字符都一样,那么 相等
,否则 不相等
。
如果两个值都是 true
,或者都是 false
,那么 相等
。
如果两个值都是 对象
,且都引用自 同一个 对象或函数,那么 相等
,否则 不相等
。
如果两个值都是 null
,或者都是 undefined
,那么 相等
。
如果其中至少有一个是 NaN
,那么 不相等
。
==
判断规则:
如果两个值 类型
相同,进行 ===
比较。
如果两个值 类型
不同,他们可能相等。根据下面规则进行类型转换再比较:
如果一个是 null
、一个是 undefined
,那么 相等
。
如果一个是 字符串
,一个是 数值
,把 字符串转换成数值 后再进行比较。
如果任一值是 true
,把它转换成 1 再比较;如果任一值是 false
,把它转换成 0 再比较。
如果一个是 对象
,另一个是 数值或字符串
,把 对象转换成基础类型 的值再比较。对象转换成基础类型在第 2 点有提到。
任何其他组合,都 不相等
。
总结规则
总的来说就是:
对于 ===
来说有如下对比规则
不同类型的值
如果两个值的类型不同,直接返回
false
。同一类型的原始类型值
同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回
true
,值不同就返回false
。需要注意的是,
NaN
与任何值都不相等(包括自身)。另外,正0 等于 负0。同一类型的复合类型值
同一类型的复合类型的值(对象、数组、函数)比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象( 是否为同一引用 )。
undefined 和 null
undefined
和null
与自身严格相等,但是两者不严格相等。
对于 ==
来说有如下对比规则
原始类型的值
原始类型的数据会转换成数值( Number )类型再进行比较。
对象与原始类型值比较
如果运算子是对象,会转为原始类型的值,再进行比较。
「对象」转换成「原始类型」的值,算法是先调用
valueOf()
方法;如果返回的还不是原始类型,再接着调用toString()
方法,得到原始类型,如果都得不到原始类型,则报错。得到原始类型后,按上方的第一点「原始类型的值」进行比较。
undefined 和 null
undefined
和null
与其他类型的值比较时,结果都为false
,它们互相比较时结果为true
,因为都表示「无」,但两者不「严格相等」,因为本质上还是不一样的,一个是未定义,一个是空。
解决问题
回到第一个问题
为什么
[1] == [1]
为false
?
答:因为这两个 Array 对象不属于同一个 引用对象 ,所以,这两个数组之间的比较结果为 false 。
- 为什么
[1] == 1
为true
?
这是因为 [1]
在和 1
进行比较的时候,首先会被转成数字类型,而转成数字类型在实现上又是通过 new Number() 来完成的。
所以,[1] == 1
会变成 Number([1]) == 1
。
同时,Number
方法接受一个 字符串 作为参数的,也就是 [1].toString()
=== '1'
,所以 Number([1])
相当于写 Number('1')
,于是很显然 Number([1])
就是 1 了。
总结
个人总结:对于相等运算符 ==
如果一边是对象,一边是基本类型,JavaScript 会先将对象使用抽象操作 ToPrimitive
将对象转换成基本类型 ( Primitive ) 之后再进行比较,之后就是基本类型之间的比较了。
一个对象转化为基本类型的步骤如下:
- 先调用该对象的
valueOf()
方法,如果返回值为基本类型
,这个值就是最终值。- 否则,继续调用对象的
toString()
方法,如果返回值为基本类型
,这个值就是最终值。- 都无法得到结果的话,抛出异常
Error: Cannot convert object to primitive value
。
注意:如果对象是 Date
实例,则先执行 toString()
方法
转换为基本类型后,再继续转换为同样类型,之后就是对其进行严格相等运算符 ===
的操作啦~
发布时间: 2017-12-03 22:25:48
原始链接: JavaScript 中「相等运算符」和「严格相等运算符」的规则和关系
许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。