ECMAScript 之数据类型转换(上)
Opened this issue · 0 comments
jejuin commented
前言
将数据从一种类型转换为另一种类型称为数据类型转换。
数据类型转换分为两种:
- 显示数据类型转换:直接调用 JS 暴露的 API 进行数据类型转换,如 parseInt,Number() 等
- 隐式数据类型转换:使用某些运算符或语句时会触发隐式数据类型转换,如 +/- 运算符,if 条件语句等
下面主要介绍了几种数据类型转换的底层算法。
以下算法均为底层 ECMAScript 规范实现,并没有暴露出来。
ToPrimitive ( input [ , PreferredType ] )
将数据类型转换为原始值。
第一个参数 input,表示要处理的输入值。
第二个参数 PreferredType ,非必填,表示希望转换成的类型,有两个值可以选,Number 或者 String。
ObjectToPrimitive
对象转为原始类型的本质是:调用内部 [[DefaultValue]] (hint)
方法,返回原始值。其中 hint 为 ToPrimitive 中的第二参数 preferredType。
[[DefaultValue]] (hint)
算法如下:
- 当没有传入 hint 时,如果对象是 String 或 Date 类型,相当于传入 String,否则,都相当于传入 Number。
- hint = String:会首先调用
toString
方法,判断是否返回原始值,如果不能返回,再调用valueOf
方法。如果都不能返回原始值,则抛出运行时错误。 - hint = Number:会首先调用
valueOf
方法,判断是否返回原始值,如果不能返回,再调用toString
方法。如果都不能返回原始值,则抛出运行时错误。
ToBoolean
将数据类型转换为布尔类型。底层调用的是 Boolean(input)
方法。
ToNumber
将数据类型转换为数字。底层调用的是 Number(input)
方法。
其中最为复杂的就是字符串转为数字类型。
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)
方法。
其中最复杂的还是数字和字符串之间的转换。
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
原始数据类型(除 null 与 undefined 外),调用各自对应的包装类型构造函数,转换为对象。
关联阅读: