【笔记】js中的类型转换(ES6)
Aug 3, 2019笔记jsesjs中的类型转换(ES6)
我们一直知道js是一种动态类型的语言,也正因为这种特性,我们使用的时候既觉得灵活有时候也会觉得坑。以下整理了ES6涉及到的转换操作。
ECMAScript会根据需要隐式执行自动类型转换。为了明确某些构造的语义,定义一组转换抽象操作是很有用的。转换抽象操作是多态的;它们可以接受任何ECMAScript语言类型或完成记录值的值。但是这些操作没有使用其他规范类型。
1 ToPrimitive(input[, PreferredType])
转换原始类型。
抽象操作ToPrimitive接受input参数和可选参数preferredType。抽象操作ToPrimitive将其输入参数转换为非对象类型。如果一个对象能够转换为多种原始类型,那么它可以使用可选的参数PreferredType来支持该类型转换。根据下表:
输入类型 | 输出结果 |
---|---|
Completion Record | 如果输入参数input是一个中断完成(break这种),返回input;否则返回ToPrimitive(input.[[value]])并且传入可选的提示PreferredType。 |
Undefined | 返回Undefined |
Null | 返回Null |
Boolean | 返回Boolean input |
Number | 返回Number input |
String | 返回String input |
Symbol | 返回Symbol input |
Object | 根据下列1.1流程: |
(其中Completion Record:完成类型是一个记录,用于解释值和控制流的运行时传播,例如执行非本地控制传输的语句,如break、continue、return和throw的行为。)
1.1 Object转为原始类型
- 1.如果PreferredType没有赋值,hint为
"default"
(hint为转换示意); - 2.如果PreferredType是String的示意,hint为
"string"
; - 3.如果PreferredType是Number的示意,hint为
"number"
; - 4.设置抽象值exoticToPrim为抽象函数GetMethod(input, @@toPrimitive)的返回结果(GetMethod用于获取对象的特定属性的值,此处即获取input的转原始类型方法);
- (中断判断exoticToPrim);
- 6.如果exoticToPrim是undefined,那么
- 设置result等于Call(exoticToPrim, input, « hint »),即执行exoticToPrim(hint);
- (中断判断result);
- 如果result是原始数据类型,返回result;
- 抛出一个TypeError异常;
- 如果hint是
"default"
,使hint为"number"
; - 返回下列OrdinaryToPrimitive(input, hint)的值。
OrdinaryToPrimitive(input, hint)
- input:Object,数据类型
- hint:String,转换示意,’string’或’number’
执行步骤:
- 1.判断input是不是对象;
- 2.判断hint是不是’string’或’number’;
- 3.如果hint是
"string"
,设置methodNames等于« "toString", "valueOf" »
; - 4.如果hint是
"number"
(记住不是’string’就是’number’),设置methodNames等于« "valueOf", "toString" »
; - 5.对刚设置的变量methodNames的每一项进行迭代并执行:
- 获取对象的执行方式,如
input.toString
- (中断判断method);
- 如果是可执行的,那么
- 设置result为执行调用结果
- 如果result的类型不是Object,返回result
- 获取对象的执行方式,如
- 抛出一个TypeError异常;
toPrimitive是可以定义修改的。Symbol.toPrimitive
来猜测一下以下执行的结果:1
2
3
4
5
6
7
8
9
10
11
12
13// Q1
var obj1 = {
[Symbol.toPrimitive] (hint) {
if (hint === 'number') {
return 123456
} else {
return '陈冠希'
}
}
};
String(obj1);
Number(obj1);
1 | // Q2 |
更多问题可见https://github.com/MichealWayne/study-js-from-questions
2.ToBoolean ( argument )
转换布尔值
抽象操作ToBoolean将参数argument转为一个布尔值。根据下表:
输入类型 | 输出结果 |
---|---|
Completion Record | 如果输入参数input是一个中断完成(break这种),返回input;否则返回ToPrimitive(input.[[value]])并且传入可选的提示PreferredType。 |
Undefined | 返回false |
Null | 返回false |
Boolean | 返回Boolean argument |
Number | 如果argument是+0 、-0 或NaN 返回false,否则返回true |
String | 如果是空字符串(’’/“”)返回false,否则返回true |
Symbol | 返回true |
Object | 返回true |
3.ToNumber ( argument )
转换为数字
抽象操作ToNumber将参数argument转为一个数字值。根据下表:
输入类型 | 输出结果 |
---|---|
Completion Record | 如果输入参数input是一个中断完成(break这种),返回input;否则返回ToPrimitive(input.[[value]])并且传入可选的提示PreferredType。 |
Undefined | 返回NaN |
Null | 返回+0 |
Boolean | 如果是true返回1,如果是false返回+0 |
Number | 返回Number argument |
String | 见下面3.1 |
Symbol | 抛出一个TypeError异常 |
Object | 第一步转为原始类型获得变量primValue,hint为’number’(ToPrimitive(argument, hint Number)),第二步调用数字转换ToNumber(primValue). |
3.1 ToNumber(String)
先判断是否合规
首先ToNumber的字符串String的应用于解释为UTF-16编码代码点序列的输入字符串。如果语法无法将字符串解释为StringNumericLiteral的扩展,即如果字符串包含任何补充代码点或任何不成对的代理代码点的UTF-16编码,则ToNumber的结果是NaN。
语法1
2
3StrWhiteSpace(opt)
或
StrWhiteSpace(opt) StrNumericLiteral StrWhiteSpace(opt)
其中
- StrWhiteSpace:空格、行终止
- StrNumericLiteral:
- StrDecimalLiteral:十进制字符
- BinaryIntegerLiteral:二进制字符
- OctalIntegerLiteral:八进制字符
- HexIntegerLiteral:十六进制字符
详细的不多说,基本要在以下字符中找:1
+ - e E 0 1 2 3 4 5 6 7 8 9 Infinity
所以像以下这种字符都不行(NaN)1
2
3'1 1'
'1a'
'infinity'
以下这种倒又是可以的1
2
3
4'\n1'
' 1'
'-1E2'
' Infinity '
再进行转换:mv
将字符串转换为数字值的整个过程与确定数字文本的数字值类似,但有些细节不同。该值分两步确定:
-
第一步,从字符串数字文本派生一个数学值(mv);
第二步,如下文所述对该数学值进行四舍五入。
具体细节在这就不记录了。
4.ToInteger ( argument )
转换为整数
抽象操作ToInteger将参数argument转为一个整数数字值。根据以下流程:
- 1.设置number为
ToNumber(argument)
; - (中断判断number);
- 2.如果number是NaN,返回+0;
- 3.如果number是+0、-0、+∞或-∞,返回number;
- 4.返回符号sign和floor(abs(number))向下取正取整。
5.ToInt32 ( argument )
转为32位整数(有符号)
抽象操作ToInt32将参数argument转为-2^31 ~ 2^31-1范围内的一个整数数值。根据以下流程:
- 1.设置number为
ToNumber(argument)
; - (中断判断number);
- 2.如果number是NaN、+0、-0、+∞或-∞,返回+0;
- 3.设置int为返回符号sign和floor(abs(number))向下取正取整;
- 4.设置int32bit按2^32取模计算;
- 5.如果int32bit大于2^31,返回int32bit-2^32,否则返回int32bit。
6.ToUint32 ( argument )
转为无符号32位整数
抽象操作ToUint32将参数argument转为0 ~ 2^32-1范围内的一个整数数值。根据以下流程:
- 1.设置number为
ToNumber(argument)
; - (中断判断number);
- 2.如果number是NaN、+0、-0、+∞或-∞,返回+0;
- 3.设置int为返回符号sign和floor(abs(number))向下取正取整;
- 4.设置int32bit按2^32取模计算;
- 5.返回int32bit
7.ToInt16 ( argument )
转为16位整数(有符号)
类似于ToInt32,范围是 −32768~32767
8.ToUint16 ( argument )
转为无符号16位整数
类似于ToUint32,范围是0 ~ 2^16−1
9.ToInt8 ( argument )
转为8位整数(有符号)
类似于ToInt32,范围是 −128~127
10.ToUint8 ( argument )
转为无符号8位整数
类似于ToUint32,范围是0 ~ 255
11.ToUint8Clamp ( argument )
与ToUint8类似,但执行步骤有所不同
- 1.设置number为
ToNumber(argument)
; - (中断判断number);
- 2.如果number是NaN,返回+0;
- 3.如果number小于等于0,返回+0;
- 4.如果number大于等于255,返回255;
- 5.设置f为number向下取整(floor(number));
- 6.如果f+0.5 < number,返回f + 1;
- 7.如果number < f+0.5,返回f;
- 8.如果f是奇数,返回f+1;
- 9.返回f。
12.ToString ( argument )
转为字符串
抽象操作ToString将参数argument转为一个字符串,根据下表:
输入类型 | 输出结果 |
---|---|
Completion Record | 如果输入参数input是一个中断完成(break这种),返回input;否则返回ToPrimitive(input.[[value]])并且传入可选的提示PreferredType。 |
Undefined | 返回字符串”undefined” |
Null | 返回字符串”null” |
Boolean | argument为true则返回字符串”true”,否则返回字符串”false” |
Number | 见下面12.1 |
String | 返回String argument |
Symbol | 抛出一个TypeError异常 |
Object | 第一步转为原始类型获得变量primValue,hint为”string”,,第二步调用字符串转换ToString(primValue). |
12.1 ToString(Number)
- 1.如果argument是NaN,返回字符串”NaN”;
- 2.如果argument是+0或-0,返回字符串”0”;
- 3.如果argument小于0,返回字符串”-“和
ToString(-argument)
; - 4.如果m是+∞,返回字符串”Infinity’;
- 5.设置整数n, k, s,其中k >= 1, 10^(k-1) <= s < 10^k。argument = s * 10^(n - k),并且k尽可能小。注意,k是s的十进制表示中的位数,s不能被10整除并且s的最低有效位不一定由这些标准唯一确定。。
- 6.如果k <= n <= 21,返回由s的十进制表示的k位数的代码单位组成的字符串(按顺序,不带前导零),然后是代码单位0x030(数字零)的n-k次出现。
- 7.如果0 < n <= 21,则返回字符串,该字符串由S的十进制表示中最有效n位的代码单位组成,然后是代码单位0x002E(完全停止),然后是S的十进制表示中剩余k-n位的代码单位。
- 8.如果−6 < n <= 0,则返回由代码单元0x030(数字零)组成的字符串,然后返回代码单元0x002E(完全停止),然后返回代码单元0x030(数字零)的−n次出现,最后返回十进制表示s的k位的代码单元。
- 9.否则,如果k=1,返回根据n−1是正数还是负数,返回由s的单个数字的代码单位组成的字符串,后跟代码单位0x0065(拉丁文小写字母E),后跟代码单位0x002b(加号)或代码单位0x002d(连字符-减号),后跟代码单位整数abs(n-1)的十进制表示(不带前导零)。
- 10.返回一个字符串,该字符串由s的小数表示形式中最有效位的代码单位组成,后跟代码单位0x002E(完全停止),然后是s的小数表示形式中剩余k−1位的代码单位,最后是代码单位0x0065(拉丁文小写字母E),然后是代码单元0x002B(加号)或代码单元0x002D(连字符-减号),根据n−1是正数还是负数,然后是整数abs(n−1)的十进制表示的代码单元(不带前导零)。
13.ToObject ( argument )
转为对象
抽象操作ToObject将参数argument转为一个Object,根据下表:
输入类型 | 输出结果 |
---|---|
Completion Record | 如果输入参数input是一个中断完成(break这种),返回input;否则返回ToPrimitive(input.[[value]])并且传入可选的提示PreferredType。 |
Undefined | 抛出一个TypeError异常 |
Null | 抛出一个TypeError异常 |
Boolean | 返回一个新的Boolean布尔对象,该对象的[[booleandata]]内部设置为参数值 |
Number | 返回一个新的Number数字对象,该对象的 [[NumberData]] 内部设置为参数值 |
String | 返回一个新的String字符对象,该对象的 [[StringData]] 内部设置为参数值 |
Symbol | 返回一个新的Symbol对象,该对象的 [[SymbolData]] 内部设置为参数值 |
Object | 返回Object argument |
14 ToPropertyKey ( argument )
转为属性键
抽象操作ToPropertyKey将参数argument转为一个能作为属性键(key)的值,流程如下:
- 1.设置key为argument转换为原始类型的值(
ToPrimitive(argument, hint String).
) - (中断判断);
- 2.如果key的类型是Symbol,返回key
- 3.将key转为字符串(ToString(key))后返回
15 ToLength ( argument )
转为适合用作类数组对象长度的整数
抽象操作ToLength将参数argument转为一个适合用作类数组对象长度的整数,流程如下:
- (中断判断argument);
- 1.设置len为argument转为整数的值(ToInteger(argument));
- (中断判断len);
- 2.如果len <= +0,返回+0;
- 3.如果len是+∞,返回2^53-1;
- 返回len和2^53-1两者的较小值(min(len, 2^53 - 1))
16 CanonicalNumericIndexString ( argument )
规范数字索引字符串
抽象操作CanonicalNumericIndexString将参数argument转为一个数值,如果该参数是ToString或字符串“-0”将生成的数字的字符串表示形式。否则,返回未定义。流程如下:
- 1.确认argument是一个字符串
- 2.如果argument是”-0”,返回-0;
- 3.设置n为argument转为数字的值(ToNumber(argument));
- 4.如果ToString(n)与argument不相同,返回Undefined
- 5.返回数字n。
规范数字字符串是CanonicalNumericIndexString抽象操作后未返回Undefined的任何字符串值。
细节点还是很多的。
Author
My name is Micheal Wayne and this is my blog.
I am a front-end software engineer.
Contact: michealwayne@163.com