ECMAScript 之数据类型转换(上)
2020-11-20 本文已影响0人
Jeuin
前言
将数据从一种类型转换为另一种类型称为数据类型转换。
数据类型转换分为两种:
- 显示数据类型转换:直接调用 JS 暴露的 API 进行数据类型转换,如 parseInt,Number() 等
- 隐式数据类型转换:使用某些运算符或语句时会触发隐式数据类型转换,如 +/- 运算符,if 条件语句等
下面主要介绍了几种数据类型转换的底层算法。
以下算法均为底层 ECMAScript 规范实现,并没有暴露出来。
ToPrimitive(input[, preferredType])
将数据类型转换为原始值。
第一个参数 input,表示要处理的输入值。
第二个参数 preferredType,非必填,表示希望转换成的类型,有两个值可以选,Number 或者 String。
image.png
ObjectToPrimitive
对象转为原始类型的本质是:调用内部[[DefaultValue]] (hint) 方法,返回原始值。其中 hint 为 ToPrimitive 中的第二参数 preferredType。
[[DefaultValue]] (hint) 算法如下:
- 当没有传入 hint 时,如果对象是 String 或 Date 类型,相当于传入 String,否则,都相当于传入 Number。
-
hint = String:会首先调用
toString方法,判断是否返回原始值,如果不能返回,再调用valueOf方法。如果都不能返回原始值,则抛出运行时错误。 -
hint = Number:会首先调用
valueOf方法,判断是否返回原始值,如果不能返回,再调用toString方法。如果都不能返回原始值,则抛出运行时错误。
ToBoolean
将数据类型转换为布尔类型。底层调用的是 Boolean(input) 方法。
image.png
ToNumber
将数据类型转换为数字。底层调用的是 Number(input) 方法。
image
其中最为复杂的就是字符串转为数字类型。
StringToNumber
ES3 规范原文:如果不能将字符串解释为 StringNumericLiteral 的扩展,则 StringToNumber 的结果为 NaN。
简单的说,就是如果字符串不符合 StringNumericLiteral 的要求,则不能进行转换。
那么 StringNumericLiteral 包含哪些内容呢?我们来看下。
- Number 类型的字符串都支持转换:如小数、十进制数、16 进制数(对于 0x 或 0X 开头的字符串会被识别为 16 进制数,对于 0 开头的八进制数不按八进制处理,而是十进制,忽略所有前导 0)、Infinity、NaN等。
console.log(Number('-1')) // -1
console.log(Number('1')) // 1
console.log(Number("Infinity")) // Infinity
console.log(Number("NaN")) // NaN
console.log(Number("1e2")) // 100
console.log(Number(".1")) // 0.1
console.log(Number("00123")) // 123
console.log(Number("-00123")) // -123
console.log(Number("0x11")) // 17
- StrWhiteSpace + StrWhiteSpaceChar:空格,
<TAB>、<SP>、<NBSP>、<FF>、<VT>、<CR>、<LF>、<LS>、<PS>、<USP>这些内容都会被转换为 0
console.log(Number("")) // 0
console.log(Number(" ")) // 0
console.log(Number('\t')) // 0
不支持转换的示例:
console.log(Number("a")) // NaN
console.log(Number("123a")) // NaN
console.log(Number('123 123')) // NaN
从上述例子可以看出,如果有一个字符不是数字,结果都会返回 NaN。
ToString
将数据类型转换为字符串。底层调用的是 String(input) 方法。
image
其中最复杂的还是数字和字符串之间的转换。
NumberToString
console.log(String(NaN)) // "NaN"
console.log(String(+0)) // "0"
console.log(String(-0)) // "0"
console.log(String(-1)) // "-1"
console.log(String(+1)) // "1"
console.log(String(Infinity)) // "Infinity"
console.log(String(0x11)) // 17
console.log(String(011)) // 9
console.log(String(1e2)) // 100
ToObject
image
原始数据类型(除 null 与 undefined 外),调用各自对应的包装类型构造函数,转换为对象。
关联阅读: