JS中的双等号(==)和三等号(===)是有很大的区别的,这是初学JS的人都知道的,但是大家都对其中运算原理不是特别清楚,这篇文章将讲述两个等号内部的运算规则,以及一些简单的总结。
运算规则
首先我们来看双等号(==)和三等号(===)的内部的运算规则。虽然有点长,但是只有详细了解其内部的详细规则,我们才能释然一些奇怪的情况(比如 [] == false
)
双等号(==)
JS中双等号(==)的判断是很复杂的,这也是最容易弄混淆的地方,所以很多的面试都会考察这一点,同时在开发中也要求尽量少使用双等号(==)。
细则
If
Type(x)
is the same asType(y)
then,Return the result of performing Strict Equality Comparison
x === y
.If x is
null
and y isundefined
, returntrue
.If x is
undefined
and y isnull
, returntrue
.If
Type(x)
isNumber
andType(y)
isString
, return the result of the comparisonx == ToNumber(y)
.If
Type(x)
isString
andType(y)
isNumber
, return the result of the comparisonToNumber(x) == y
.If
Type(x)
isBoolean
, return the result of the comparisonToNumber(x) == y
.If
Type(y)
isBoolean
, return the result of the comparisonx == ToNumber(y)
.If
Type(x)
is eitherString
,Number
, orSymbol
andType(y)
isObject
, return the result of the comparisonx == ToPrimitive(y)
.If
Type(x)
isObject
andType(y)
is eitherString
,Number
, orSymbol
, return the result of the comparisonToPrimitive(x) == y
.Return
false
.
精简
在上面我们可以看出,双等号(==)的运算规则简单的就是如下规则:
判断两边的变量
是否同类型
,如果同类型就返回三等号(===)的运算的结果。判断两边的变量
是否一个为 null 一个为 undefined
,如果是就返回true
。ps:可以简单的记为
null == undefined
为true
判断两边的变量
是否一个为 Number类型 一个为 String类型
,如果是,则将String类型的变量使用ToNumber
方法转换为Number类型 再执行比较。ps:相当于
'123' == 1
转化为123 == 1
判断是否有一边为
Boolean类型
, 如果有则对这个Boolean类型变量使用ToNumber
方法转换为Number类型 再执行比较。ps:结合上面
'2' == true
先转换为'2' == 1
, 在转换为2 == 1
判断两边的变量
是否一个为 Number、String、symbol类型 一个为 Object类型
,如果是则对Object类型的变量执行ToPrimitive
方法的转换后再进行比较如果上面的条件都没有满足,那么直接返回
false
三等号(===)
JS中双等号(==)的判断是很简单,它的规则也同样简单。
细则
If
Type(x)
is different fromType(y)
, returnfalse
.If
Type(x)
isNumber
, thenIf x is
NaN
, returnfalse
.If y is
NaN
, returnfalse
.If x is the same Number value as y, return
true
.If x is
+0
and y is-0
, returntrue
.If x is
-0
and y is+0
, returntrue
.Return
false
.
Return
SameValueNonNumber(x, y)
.
精简
三等号(===)的运算规则就很简单:
类型不同返回
false
数值类型
NaN
永远返回false
其余的基础类型直接比较值是否相等
对象比较引用是否相同。
特别的转换函数
上面可以看到,在运算中使用了 ToNumber
,ToPrimitive
,SameValueNonNumber
这3个函数,虽然看名字就能知道它是干啥的,但是其中还是有一些坑
ToNumber
Argument Type | Result |
---|---|
Undefined | Return NaN . |
Null | Return +0 . |
Boolean | Return 1 if argument is true . Return +0 if argument is false . |
Number | Return argument (no conversion). |
String | See grammar and conversion algorithm below. |
Symbol | Throw a TypeError exception. |
Object | Apply the following steps: Let primValue be ? ToPrimitive(argument, hint Number) .Return ? ToNumber(primValue) . |
其中 String
到 Number
的转换是最复杂的,将单开一片文章进行讲解。
ToPrimitive
这个方法的算法看似复杂,其实就是主要将对象转换为基本数据类型。
详细可参看参考资料中的链接ToPrimitive
只需要记住:
优先转换为
String
时,依次调用对象的toString
和valueOf
,获取最先返回不是对象的那个值优先转换为
Number
时,依次调用对象的valueOf
和toString
,获取最先返回不是对象的那个值Number默认转换是默认转换为
Number
。
SameValueNonNumber
这个方法就是比较不是数字的两个值
Assert:
Type(x)
is notNumber
.Assert:
Type(x)
is the same asType(y)
.If
Type(x)
isUndefined
, returntrue
.If
Type(x)
isNull
, returntrue
.If
Type(x)
isString
, thenIf
x
andy
are exactly thesame sequence of code units
(same length and same code units at corresponding indices), returntrue
;otherwise, return
false
.If
Type(x)
isBoolean
, thenIf
x
andy
areboth true
orboth false
, returntrue
;otherwise, return
false
.If
Type(x)
isSymbol
, thenIf
x
andy
are both the sameSymbol value
, returntrue
;otherwise, return
false
.Return
true
ifx
andy
are the same Object value.Otherwise, return
false
.
从上面的算法不难看出其实就是很普通的比较,相信看一看就能懂。
一些感到奇怪的情况
这里将列出一些让人感觉奇怪的等式,并给出转换过程
[] == false 为true
[] == false
[] == 0 //转换boolean
‘’ == 0 //转换对象 调用array的toString
0 == 0 //转换string为number
[0] == false 为true
[0] == false
[0] == 0 //转换boolean
‘0’ == 0 //转换对象 由于Array是调用的Object的valueOf,返回的为对象,将继续调用array的toString来获取非对象类型数值
0 == 0 //转换string为number
‘2’ == true 为false
‘2’ == true
‘2’ == 1 //转换boolean
2 == 1 //转换string
undefined == 0 和 null == 0 为false
undefined
和 null
必须相互比较或者相同才会为 true
参考资料
END
2017-04-19 完成
2017-04-12 立项