JS 的隐式转换给我们带来了不少便利,然而在一些时候,过度的使用也会导致一些不可预料的问题,比如 1 + '1'
的结果,这是一类经常要注意的简单问题。隐式转换属于类型转换的一部分,类型转换是一个简单而又繁杂的话题。这篇文章旨在理清楚其中的一个相关操作 相等运算符。
相等运算其中包括抽象相等(==)和严格相等(===),它们之间的区别仅在与,严格相等会直接比较类型,而不会做一些隐式转换。其实所谓的隐式转换,只是 EMCA 中规定的一些操作逻辑而已,今天,我们就深入其中,看看这层转换的外壳之下,究竟包含这什么。
相等运算符转换规则
比较 x == y
,x
和 y
都是值,返回 true
或者 false
。一个比较会执行如下步骤: 注: Type[x]
理解为 x 的类型。ToNumber
和 ToPrimitive
是类型转换中的一种处理,后面会提到。
- 如果
Type[x]
和Type[y]
的类型相同,那么执行严格相等比较。(所以说,可以理解为===
是==
的步骤之一) - 如果
x
是 null 并且y
是 undefined,那么返回 true。 - 如果
x
是 undefined 并且y
是 undefined,那么返回 true。 - 如果
Type[x]
是 Number 并且Type[y]
是 String,返回x == !ToNumber(y)
的比较结果。 - 如果
Type[x]
是 String 并且Type[y]
是 Number,返回!ToNumber(x) == y
的比较结果。 - 如果
Type[x]
是 Boolean,返回!ToNumber(x) == y
的比较结果。 - 如果
Type[y]
是 Boolean,返回x == !ToNumber(y)
的比较结果。 - 如果
Type[x]
是 String,Number 或者 Symbol 并且Type[y]
是 Object,返回x == ToPrimitive[y]
的比较结果。 - 如果
Type[x]
是 Object并且Type[y]
是 String,Number 或者 Symbol,返回ToPrimitive[x] == y
的比较结果。 - 返回 false
化繁为简
上面的 10 条内容看起来头头是道,可是用来记忆就有诸多不便了。总结如下:
类型相同比较值,
null,undefined 总为 true。
Number,String,ToNumber,
若有 Boolean 也 ToNumber。
Object 要 ToPrimitive,
其他结果返回 false。
复制代码
规则搞清楚以后,只需要弄明白 ToNumber
和 ToPrimitive
是什么就万事大吉了。我们先从简单的说起,
ToNumber 的规则,官方给出一个表格:
参数类型 | 结果 |
---|---|
Undefined | 返回 NaN |
Null | 返回 +0 |
Boolean | 如果 argument 是 true,返回 1,否则返回 0 |
Number | 返回 argument 没有转换 |
String | 参考下面的转换算法 |
Symbol | 抛出类型错误 |
Object | 两步走: 1. 转换成基本值, ToPrimitive(argument, hint Number) 2. 返回 ToNumber() |
好了,到此为止,似乎对 Obejct 的比较运算处理起来需要多一步先转换为数字(也只能这样),再跟具体 ToNumber
比较,由此我们可以进一步推测,在处理字符串,布尔值等基本数据类型的时候,应该会有 ToBoolean
或者 ToString
等等的内置工具(实际上类型转换的规则更多具体,ECMA 中有很详细的介绍)。这里要挖个坑,关于上图表格中的字符串转换算法,我有点看不懂 ECMA 中的介绍,需要继续研究。
关于 ToPrimitive
的内容也很简单,断言处理输入值,然后根据输入类型做不同处理得到基本值。