相等不相等?
先来随便举几个🌰 吧~javascript
'0' == true
[1] == [1]
[1] == 1
null == false
null == undefined
NaN === NaN
+0 === -0
Object.is([], [])
Object.is(-0, +0)
Object.is(NaN, NaN)
var arr = [NaN, 0, +0]
arr.indexOf(-0)
arr.indexOf(NaN)
arr.includes(-0)
arr.includes(NaN)
复制代码
可能 ±0、NaN 会纠结一点,仍是比较基础的,也许不少人一眼扫过去便知道答案了,网上也已经有了不少相关的经验总结。我在这里结合官方规范进行了整理,但愿能带给你不同的认识。java
预备知识
ECMAScript Language Types
传送门。根据最新规范,EcmaScript 一共有7种语言类型:编程
- Undefined
- Null
- Number
- String
- Boolean
- Symbol
- Object
咱们常常把 Object 类型称为 引用数据类型,其它5种则为基本数据类型。(Symbol怎么说..?网络
ToNumber
传送门。任意 EcmaScript 类型转化为 Number 类型:ecmascript
类型 |
结果 |
Undefined |
NaN |
Null |
+0 |
Boolean |
true -> 1,false -> +0 |
Number |
不转变 |
String |
空字符串 -> +0,有效的数字 -> 十进制数字,其它 -> NaN |
Object |
先ToPrimitive(hint Number),再ToNumber |
Symbol |
抛错,TypeError 错误 |
ToPrimitive
传送门。内部方法,主要功能是将引用数据类型转化为基本数据类型。编程语言
- 根据内部标记
hint
的不一样有不一样的调用顺序。
hint
有三种:default、number、string。default 默认遵守 number 规则。
- default/number:先 valueOf,后 toString。通常转化规则皆如此。
- string:先 toString,后 valueOf。如Date对象方法、String()转化等。
- 若是 toString/valueOf 中某一方法返回类型不为对象类型,则直接返回该值,不会继续调用后面方法。若是二者都返回对象类型,会抛 TypeError 错误。
-0、+0、0 的疑惑
明明平常没什么卵用,为何会有±0?ui
- 其实听从
IEEE754
标准的编程语言都有±0的概念,IEEE754
标准的64位浮点数,是以1+11+53
形式的符号位+阶数位+尾数位
表示。
- 符号位、阶数位、尾数位都是0,那即是
+0
,也就是常规的数字0
。
- 符号位为1,阶数位、尾数位都是0,那即是
-0
。
IEEE754
还规定了NaN
、无穷
及其它的相应规范,有兴趣可自行查找相关资料。
PS
这部分实际上是后加的,你会发现每一个知识点都是紧密相连的,构成了一个庞大的知识网络,限于篇幅我不会详细介绍,但我会尽可能贴出规范出处,你们可自行研究。编码
SameValueNonNumber 内部方法
SameValueNonNumber 方法接收两个参数 x 和 y ,其中 x 和 y 都不是 Number 类型,该方法返回 true 或 false。spa
主要规则
- 断言:x 不是 Number 类型。
- 断言:x 和 y 是 相同类型。
- 若是 x 是 Undefined 类型,返回 true 。
- 若是 x 是 Null 类型,返回 true 。
- 若是 x 是 String 类型:
- 若是 x 和 y 长度相同且相应编码单元相同,返回 true 。
- 不然返回 false 。
- 若是 x 是 Boolean 类型:
- 若是 x 和 y 都是true 或者 都是false,返回 true 。
- 不然返回 false 。
- 若是 x 是 Symbol 类型:
- 若是 x 和 y 都是相同 Symbol 值,返回 true 。
- 不然返回 false 。
- 若是 x 和 y 指向同一对象,返回 true 。不然返回 false 。
小结
相同类型比较规则(除Number类型)prototype
- 都是 undefined,相等。
- 都是 null,相等。
- String 类型中,都是相同字符串,相等。
- Boolean 类型中,都是 true 或者 都是 false,相等。
- Symbol 类型中,都是相同 Symbol 值,相等。
- Object 类型中,引用同一对象,相等。
使用
哪些 JavaScript 公开方法采用了 SameValueNonNumber 比较呢?
- 公开方法木有
- 接着看下去你就会知道,撇开数值类型比较,
SameValueNonNumber
是 SameValue
、SameValueZero
、 ===
的公共方法。
SameValueZero 内部方法
SameValueZero 方法接收两个参数 x 和 y ,其中 x 和 y 是 EcmaScript 任意类型值,该方法返回 true 或 false。
主要规则
- 若是 x 和 y 的类型不一样,返回 false 。
- 若是 x 是 Number 类型:
- 若是 x 和 y 都是 NaN ,返回 true 。
- 若是 x 是 -0 ,y 是 +0 ,返回 true 。
- 若是 x 是 +0 ,y 是 -0 ,返回 true 。
- 若是 x 和 y 数值相等,返回 true 。
- 返回 false 。
- 返回 SameValueNonNumber(x, y) 方法的返回值。
小结
- 不一样类型不相等。
- Number 类型中:±0 相等。NaN 和 NaN 相等。其它相同数值相等。
SameValueNonNumber
比较:
- 都是 undefined,相等。
- 都是 null,相等。
- String 类型中,都是相同字符串,相等。
- Boolean 类型中,都是 true 或者 都是 false,相等。
- Symbol 类型中,都是相同 Symbol 值,相等。
- Object 类型中,引用同一对象,相等。
使用
哪些 JavaScript 公开方法采用了 SameValueNonNumber 比较呢?
- Array.prototype.includes
- Map.prototype.delete
- Map.prototype.has
- Map.prototype.set
- Set.prototype.delete
- Set.prototype.has
- Set.prototype.add
- ArrayBuffer 和 DataView 部分方法
SameValue 内部方法
SameValue 方法接收两个参数 x 和 y ,其中 x 和 y 是 EcmaScript 中任意类型值,该方法返回 true 或 false。
主要规则
- 若是 x 和 y 的类型不一样,返回 false 。
- 若是 x 是 Number 类型:
- 若是 x 和 y 都是 NaN ,返回 true 。
- 若是 x 是 -0 ,y 是 +0 ,返回 false 。
- 若是 x 是 +0 ,y 是 -0 ,返回 false 。
- 若是 x 和 y 数值相等,返回 true 。
- 返回 false 。
- 返回 SameValueNonNumber(x, y) 方法的返回值。
小结
- 不一样类型不相等。
- Number 类型中:±0 不相等。NaN 和 NaN 相等。其它相同数值相等。
SameValueNonNumber
比较:
- 都是 undefined,相等。
- 都是 null,相等。
- String 类型中,都是相同字符串,相等。
- Boolean 类型中,都是 true 或者 都是 false,相等。
- Symbol 类型中,都是相同 Symbol 值,相等。
- Object 类型中,引用同一对象,相等。
使用
哪些 JavaScript 公开方法采用了 SameValueNonNumber 比较呢?
- Object.is
- 在最新的 ES 规范 中,你会发现许多其它内部方法和公开方法都应用了
SameValue
比较方法,其中大部分也没有涉及数值比较。
- 至于为何是
SameValue
方法,而不是 SameValueZero
或===
。其实我也不知道。。。我我的倾向于认为:SameValue 方法本来在 ES5 规范中便存在了,最新的规范是为了保持规范一致而继续沿用。
=== 严格相等运算
Strict Equality Comparison,x === y,返回 true 或者 false。
主要规则
- 若是 x 和 y 的类型不一样,返回 false 。
- 若是 x 是 Number 类型:
- 若是 x 是 NaN ,返回 false 。
- 若是 y 是 NaN ,返回 false 。
- 若是 x 和 y 数值相等,返回 true 。
- 若是 x 是 -0 ,y 是 +0 ,返回 true 。
- 若是 x 是 +0 ,y 是 -0 ,返回 true 。
- 返回 false 。
- 返回 SameValueNonNumber(x, y) 方法的返回值。
小结
- 不一样类型不相等。
- Number 类型中:±0 相等。NaN 和 NaN 不相等。其它相同数值相等。
- SameValueNonNumber比较:
- 都是 undefined,相等。
- 都是 null,相等。
- String 类型中,都是相同字符串,相等。
- Boolean 类型中,都是 true 或者 都是 false,相等。
- Symbol 类型中,都是相同 Symbol 值,相等。
- Object 类型中,引用同一对象,相等。
使用
哪些 JavaScript 公开方法采用了 === 比较呢?
- === 严格相等运算
- 左右两边是相同类型的 == 相等运算
- switch语句中的case
- Array.prototype.indexOf
- Array.prototype.lastIndexOf
== 相等运算
Abstract Equality Comparison,x == y,返回 true 或者 false。
主要规则
- 若是 x 和 y 的类型相同:
- 若是 x 是 null ,y 是 undefined ,返回 true 。
- 若是 x 是 undefined ,y 是 null ,返回 true 。
- 若是 x 是 Number 类型 ,y 是 String 类型,返回 x == ToNumber(y) 运算结果。
- 若是 x 是 String 类型 ,y 是 Number 类型,返回 ToNumber(x) == y 运算结果。
- 若是 x 是 Boolean 类型 ,返回 ToNumber(x) == y 运算结果。
- 若是 y 是 Boolean 类型 ,返回 x == ToNumber(y) 运算结果。
- 若是 x 是 Number、String、Symbol 中任意一个类型 ,y 是 Object 类型,返回 x == ToPrimitive(y) 运算结果。
- 若是 y 是 Number、String、Symbol 中任意一个类型 ,x 是 Object 类型,返回 ToPrimitive(x) == y 运算结果。
- 返回 false 。
小结
- 相同类型:遵循 === 严格相等比较规则。
- null == undefined,相等。
- 不一样类型:
- 基本数据类型转换为 Number 类型再 == 比较。
- 引用数据类型执行内部 ToPrimitive方法后再 == 比较。
使用
哪些 JavaScript 公开方法采用了 == 比较呢?
- 只有这只 == 相等运算
相等不相等
开头的答案。若是对结果感到好奇,不妨对着上面的过程比对~
'0' == true
[1] == [1]
[1] == 1
null == false
null == undefined
NaN === NaN
+0 === -0
Object.is([], [])
Object.is(-0, +0)
Object.is(NaN, NaN)
var arr = [NaN, 0, +0]
arr.indexOf(-0)
arr.indexOf(NaN)
arr.includes(-0)
arr.includes(NaN)
复制代码
总结
-
SameValueZero
、SameValue
、===
这仨彻底差很少嘛!
- 相同点:
- 不一样类型即不相等。
- 相同类型听从
SameValueNonNumber
规则。
- 不一样点:对
±0
、NaN
的判断上各有不一样。
-
以 Array.prototype.includes 为表明的SameValueZero
-
以 Object.is 为表明的SameValue
-
以 ===、Array.prototype.indexOf 为表明的===
-
==
- 相同类型采用
===
严格比较。
- 不一样类型会隐式转换:
- 基本数据类型转换为 Number 类型再 == 比较。
- 引用数据类型执行 ToPrimitive 转换后再 == 比较。
- undefined/null 特例。