JS对象到原始值转换的复杂性 主要由于某些对象类型存在不止一种原始值的表示
对象到原始值转换的三种基本算法
在解释三种算法前需要了解
toString
valueOf
这两个方法
toString
- 返回对象的字符串表示
Array
类的toString
方法会将每个元素转换为字符串,再使用逗号作为分隔符拼接起来Function
类的toString
方法将定义的函数转换为JS源代码的字符串Date
类型的toString
方法返回一个人类友好(且JS可解析)的日期和时间字符串RegExp
类定义的toString
方法将RegExp对象
转换为一个看起来像RegExp字面量的字符串
valueOf
- 把对象转换为代表对象原始值(如果存在这样一个原始值)
- 对象是复合值,且多数对象不能真正通过一个原始值标识,
valueOf
方法默认情况只返回对象本身 String
Number
Boolean
包装类定义的valueOf
返回被包装的原始值Array
Function
RegExp
继承默认方法,返回对象本身Date
对象返回日期的内部表示形式:自1970年1月1日至今的毫秒数
偏字符串
(该算法返回原始值,只要可能就返回字符串)
- 首先尝试
toString
方法 - 方法有定义且返回原始值,则使用该原始值(即使这个值不是字符串)
- 不存在或者存在但返回对象,则尝试使用
valueOf
方法 - 方法存在且返回原始值,则使用该值。
- 否则,转换失败
TypeError
偏数值
(该算法返回原始值,只要可能就返回数值)
- 与
偏字符串算法
类似,先尝试valueOf
再尝试toString
无偏好
(该算法不倾向于任何原始值类型,而是由类定义自己的转换规则)
- 取决于被转换对象的类
- 如果是
Date
对象,则使用偏字符串算法
- 其他类型使用
偏数值算法
JS内置类型除了Date类都实现了偏数值算法;Date类实现了偏字符串算法
对象转换为布尔值
- 所有对象都转换为
true
- 不需要使用前面的转换算法
- 包括空数组、
new Boolean(false)
包装对象
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) /// true
对象转换为字符串
- 使用
偏字符串
算法转换为一个原始值 - 再将原始值转换为字符串
String({}) // '[object Object]'
String([]) // ''
String(new Date(2023)) // 'Sun Jan 01 2023 08:00:00 GMT 0800 (中国标准时间)'
String(new RegExp(/[a-z]/i)) // '/[a-z]/i'
对象转换为数值
- 使用
偏数值
算法转换为一个原始值 - 将原始值转换为数值
Number({}) // NaN
Number([]) // 0
Number([6]) // 6
Number(new Date(2023)) // 1672531200000
Number(new RegExp(/[a-z]i/)) // NaN
操作符转换特例
操作符
- 执行数值加法和字符串拼接
- 如果一个操作数是对象,则使用
无偏好算法
将对象转换为原始值 - 如果两个操作数都是原始值,则检查类型
- 有一个是字符串,则将另一个转换为字符串进行拼接
- 否则转换为数值进行相加
==
!=
操作符
- 允许类型转换的宽松方式执行相等和不相等测试
- 如果一个操作数是对象 另一个是原始值,则使用
无偏好算法
转换为原始值 再比较
< <= > >=
关系操作符
- 既可比较数值也可比较字符串
- 如果有一个操作数是对象 则使用
偏数值算法
将对象转换为原始值 - 与对象到数值转换不同 这个
偏数值算法
返回的原始值不会再被转换为数值