JavaScript是一门弱类型语言,其灵活的设计初衷也带来了隐式转换的弊端;下面是对js数据类型转换的梳理
首先得知道js的数据类型6种基本数据类型与object
6种基本数据类型(含es6):null
、undefined
、string
、number
、boolean
、symbol
(es6新增)
隐式转换js内部的相关方法
要深入理解js的隐式转换,得先知道几个js内部与隐式转换相关的方法(不需要深入理解的可以跳过)
这是js内部实现的方法,我们是无法直接调用的
ToPrimitive(input, [PreferredType])
具体处理逻辑可查看ECMA-262关于ToPrimitive的说明;此方法用于js内部将非基本数据类型数据转为基本类型数据,方法逻辑可以简单概括为:
- 1.PreferredType的值默认为default,可选值还有string、number
- 2.当PreferredType为number时,会先调用input的valueOf方法,如果得到了基本数据类型,就以此当返回值;如果没有,则调用toString方法
- 3.当PreferredType为string时,会先调用toString方法,然后走类似步骤2的逻辑
- 4.当PreferredType为default时,与为number时处理逻辑一致
ToBoolean(argument)
具体处理逻辑可查看ECMA-262关于ToBoolean的说明;此方法为js内部将数据转为boolean
类型;可以概括为(感觉没啥好概括的,就把ecma的描述翻译一遍了):
原数据类型 | 转换成boolean 后的结果 |
---|---|
undefined | false |
null | false |
number | 0 、-0 、NaN 转为false ,其他为true |
string | 长度为0的转为false ,其他为true |
symbol | true |
Object (所有非原始类型的) | true |
ToString(argument)
具体处理逻辑可查看ECMA-262关于ToString的说明;此方法为js内部将数据转为string
类型;同样简单翻译下ecma文档:
原数据类型 | 转换成string 后的结果 |
---|---|
undefined | 'undefined' |
null | 'null' |
boolean | false => 'false' , true => 'true' |
symbol | 报错 |
number | -0 => '0' ,NaN => 'NaN' , 其他转换 => number 对应的字符串 |
ToNumber(argument)
具体处理逻辑可查看ECMA-262关于ToNumber的说明;此方法为js内部将数据转为number
类型;同样简单翻一下ecma文档:
原数据类型 | 转换成number 后的结果 |
---|---|
undefined | NaN |
null | 0 |
boolean | true => 1 , false => 0 |
undefined | NaN |
symbol | 报错 |
string | 逻辑比较多,见下面的内容 |
object (所有非原始类型的) | ToPrimitive(object, number) |
string
转number
string
首尾的空格会被忽略,所以下面不讨论首尾有空格的情况;数字部分首尾的0也会被忽略
- 字符串里为纯数字或者带小数点的数字时,转为对应number
new Number('11') // 11
new Number('11.11') // 11.11
- 字符串以
0x
(x
可以是大写)开头
new Number('0x12') // 18,即将18转换成16进制
new Number('0x') // NaN
new Number('0x12z') // NaN,z无法转换成对应的16进制
0b
(二进制)、0o
(八进制)与0x
类似- 字符串中含有
\u0031
unicode码,会将unicode码转换成对应字符后处理 ''
长度为0的字符串会转换成0- 纯不可见转义字符(
'\r'
、'\n'
等等)会转换成0 - 其他会转换成
NaN
隐式转换
转换场景
抽象相等
==
运算符的隐式转换:
1.类型相同时等同于===
2.类型不相同时,会将两边转换为number
进行比较
3.一边是非原始类型的会通过ToPrimitive(input)转换成原始类型后处理两边都是对象时
==
运算符比较的是对象内存地址
除Date外,ToPrimitive(input)会优先调用valueOf转换,Date因为内部做了特殊处理,会先调用toString,具体原理可见ecma对应文档抽象比较运算符(如
>=
、<=
等等)的隐式转换:- 如果两边都是
string
,会从左至右一次比较字符的unicode码 - 否则会将两边转换为
number
进行比较 - 非原始类型的会通过ToPrimitive(input, number)转换成number后处理
- 如果两边都是
- 逻辑运算符(
||
、&&
、!
)的隐式转换:
会将数据转换成boolean
- 算数运算符(
+
、-
、*
、/
、>>
)的隐式转换:
会将数据转换成number后进行处理
- 非原始类型的会通过ToPrimitive(input, number)转换成number后处理
这里的+
不是字符串拼接+
至少有一边是string
时会进行字符串拼接,会将非字符串的数据转成字符串
注意:不含symbol是因为symbol不能转换
显示转换
parseInt
看mdn的api就好,简单易懂
Number.prototype.toString(rdx)
看mdn的api就好
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。