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
nulland y isundefined, returntrue.If x is
undefinedand y isnull, returntrue.If
Type(x)isNumberandType(y)isString, return the result of the comparisonx == ToNumber(y).If
Type(x)isStringandType(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, orSymbolandType(y)isObject, return the result of the comparisonx == ToPrimitive(y).If
Type(x)isObjectandType(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
+0and y is-0, returntrue.If x is
-0and 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
xandyare exactly thesame sequence of code units(same length and same code units at corresponding indices), returntrue;otherwise, return
false.If
Type(x)isBoolean, thenIf
xandyareboth trueorboth false, returntrue;otherwise, return
false.If
Type(x)isSymbol, thenIf
xandyare both the sameSymbol value, returntrue;otherwise, return
false.Return
trueifxandyare 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 立项