JavaScript类型转换(二)——如何转换

这是JavaScript类型转换系列文章的第二篇,讲述如何向3个基本类型转换。

如何转换

前文已经说过,类型转换的最终目标是3个基本类型:numberstringboolean。本篇就是要讲解数据向这三个方向转换的细节。

首先需要讲引用类型数据如何向numberstring转换,至于为什么没有boolean方向,读完本篇就会知道。

引用类型的ToPrimitive流程

ToPrimitive流程由JavaScript宿主环境实现,影响引用类型转换结果。

这个流程有很多细节,我们只需要了解:

  1. 进入这个流程时传入的转换方向很重要,通常转换方向倾向于number
  2. 引用类型上的[Symbol.toPrimitive]函数结果最优先;
  3. 引用类型上的toStringvalueOf函数的结果作为备选,转换方向影响它俩的优先顺序;
  4. 如果上述3个函数的返回仍然是引用类型,则会抛出TypeError异常。

不需要担心引用类型没有toString()valueOf()函数,JavaScript中所有引用对象的根父类Object定义了这两个函数,它的子孙类型只需要覆盖这两个函数就可以实现自定义。JavaScript内置的类型,绝大多数valueOf()返回的是其自身,toString()有各自的差异,如下表:

数据类型 valueOf返回 toString返回
Number 原始值 对应字符串
String 原始值 对应字符串
Boolean 原始值 对应字符串
Date 时间戳 日期时间字符串
Array 对象自身 [数组元素拼接成的字符串(用逗号分隔)]
Function 对象自身 函数源代码字符串
RegExp 对象自身 正则字符串
Object 对象自身 字符串:[object Object](注意大小写)

这里有一个疑问:进入这个流程时传入的那个转换方向参数,是由谁来控制决定的?答案在后面。

向字符串转换

在确定向字符串转换后,转换的规则如下:

转换前的数据 结果 举例or说明
string 原值
Symbol Symbol(描述字符串) 不支持隐式转换
undefined "undefined"
null "null"
true "true"
false "false"
BigInt 转对应的10进制数字字符串,去掉末尾的n 0x10n->"16"
引用类型 执行其ToPrimitive流程,转换方向为string,对得到的结果再执行向字符串转换操作

numberstring转转换规则如下:

number向字符串转换 结果 举例
NaN "NaN"
-0 "0"
Infinity "Infinity"
-Infinity "-Infinity"
小数部分等于0的数字 舍弃小数部分后再转换 12.0->"12"
极大值或极小值 对应的科学记数法字符串 0.000000001->"1e-9"
非10进制表示的数字 对应的10进制数字字符串 0x10->"16"
其它情况 对应的字符串

向数字转换

在确定向数字转换后,转换的规则如下:

转换前的数据 结果 举例or说明
number 原值
ture 1
false 0
null 0
undefined NaN
Symbol 抛出TypeError
BigInt 对应的 Number类型数字 可能会丢失精度。不会隐式转换为Number类型
引用类型 尝试执行其ToPrimitive流程,转换方向为number,对得到的结果再执行向数字转换操作 Number([10])->10

stringnumber转换的情况稍复杂:

  • 在做转换前,字符串头尾的空白字符(包括回车换行制表等)都会被剔除

  • 空字符串转换为:0

  • 字符串中多个前导0的会被替换为1个

  • 合法的数字字符串会被转换为对应数字,包括如下:

    • 2、8、10、16进制数字字符串
    • 极大极小值数字字符串
    • 科学计数法数字字符串
    • "Infinity""-Infinity"
    • NaN
  • 不合法的字符串符串(包括BigInt数字字符串):NaN

向布尔值转换

向布尔值转换的结果,大多数情况为true,以下是转换为false的情况:

  1. false
  2. 空字符串
  3. null
  4. undefined
  5. 0
  6. -0
  7. NaN
  8. 0n
  9. document.all

总结

本篇讲述的在确定转换方向后,各种数据类型转换的规则。

其中引用类型的转换规则最复杂,有必要掌握为数不多的几个内置引用类型的toString()valueOf()返回什么结果,进阶应该掌握通过自定义[Symbol.toPrimitive]函数控制类型转换的方法。

字符串和数字相互转换,需要掌握特殊情况。

向布尔值转换的规则最简单,引用类型的[Symbol.toPrimitive]函数没有必要处理这个转换方向的情况。

下一篇讲如何确定转换方向。