携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
JS数据类型转换规则(一)
引言
- 在我们平常工作中,经常会听到这样的diss, 你怎么还用 === ,多写个== 能
()
啊。但是当你看一个库的实现,又会使用 ==,比如同时判断 null,undefined。再比如 你需要将一个数字转为为字符串,或者将字符串转为数字,会使用+ ''
,*1
,这些小技巧。再比如要获取当前时间戳,你不想使用new Date().getTime
, 直接使用+new Date()
也可以得到相同的结果。这些小的知识点,都和js的类型转化有关。下面就让我们一起学习js中的类型转换规则
其他数据类型转换为Number
- 数据转换分隐式转换,和显式转换。隐式转换一般是浏览器去使用
Number(val)
默认做转换。显示转换 也可以使用parseInt
,parseFloat
,当然如果你显示使用Numebr()
,也是可以的
隐式转换(Nunber)
- 数字运算(-,*)
8 - '2' = 6
实际上浏览器会使用Number先将‘2’,进行隐式转换 Number('2') // 2
'12' * 1 = 12 (常用于字符串转数字)
- isNaN检测(检测是不是不是有效数字)
isNaN('1') // false
实际上浏览器会使用Number先将'1',进行隐式转换 Number('1') // 1
==
比较
1 == true
实际上浏览器会使用Number先将true,进行隐式转换 Number(true) // 1
隐式转换规则
- 字符串 转换为 数字: 空串变为0,如果出现任何非有效数字的字符,结果都是NaN
- 空串变为0
8 - '' = 8 等价于 8 - 0 = 8
因为 Number('') = 0;
- 非有效字符结果都是NaN
8 - '12px' = NaN
因为 Number('12rpx') // NaN
- 布尔值转换为数字: true -> 1 ; false -> 0
- true -> 1
4- true = 3
因为 Number(true) // 1
- false -> 0
5 - false = 5
因为 Number(false)// 0
- null -> 0 ; undefined -> NaN
5 - null = 5
因为 Number(null) // 0
5 - undefined = 5
因为 Number(undefined) // NaN
- Symbol 无法转换为数字,会报错
5. BigInt 去除“n”, 超过最大安全数,会不准确
Number(10n) 10
6. 对象转换为数字(重点)
-
- 先调用对象的
Symbol.toPrimitive
这个方法,如果不存在这个方法
- 先调用对象的
-
- 再调用对象的valueof获取原始值,如果获取的值不是原始值
-
- 再调用对象的toString, 把其变为字符串
-
- 最后再把字符串基于Number 转换为数字
demo1: 获取时间戳
- 标准获取方式
利用类型转换获取
利用类型转换获取(流程介绍)
- 首先检测[Symbol.toPrimitive] 有没有,如果有,并且是个函数,则调用
let timer = new Date()
timer[Symbol.toPrimitive]('number') // 1661672839917
这个结果和Number(timer是一样的)
转换完毕
demo2: 将数组转换为数字
5 - [3] = 2
- 首先检测[Symbol.toPrimitive] 有没有,如果有,并且是个函数,则调用
数组没有这个方法,那么接着走下面的判断
- 调用对象的valueof获取原始值
获取的值不是原始值,那么接着判断
- 调用对象的toString, 把其变为字符串
- 最后再把字符串基于Number 转换为数字
结果:5 - [3] = 2。因为数组经过一系列的隐式转换,变为了数字3。
如果数组个数大于1
,看看会出现什么情况
因为转换为字符串时,出现了非有效数字的字符,
,所以结果是NaN
显示转换
parseInt()
- parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数,
radix
是 2-36 之间的整数,表示被解析字符串的基数。(如果不写,或者是0,默认是10。有效范围是2-36,不在这个区间,则返回NaN)
parseInt('123', 5) // 将'123'看作 5 进制数,返回十进制数 38
=> 1*5^2 + 2*5^1 + 3*5^0 = 38
parseInt('12px', 10) // 12
parseInt('12.9px', 10) // 12
parseInt('12px') // 12
parseInt('12px', 0) // 12
parseInt('12d', 37) // NaN
parseInt('d12px', 10) // NaN
parseInt(null) // NaN
parseInt(undefined) // NaN
parseFloat()
parseFloat()
函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。如果给定值不能被转换成数值,则会返回 NaN
。
parseFloat('12.9') // 12.9
parseFloat('12.9px') // 12.9
parseFloat('12.9px') // 12.9
parseFloat('12.9px') // 12.9
parseFloat('12.9d') // NaN
parseFloat('d12px') // NaN
demo练习
let arr = [27.2, 0, '0013', '14px', '123']
arr = arr.map(parseInt)
我们具体剖析一下
- map
arr = arr.map((item, index) => {
return item * index
})
如果将parseInt 作为参数传入,相当于如下代码
根据参数要求: 如果参数不是一个字符串,则将其转换为字符串 (使用 ToString
抽象操作)
所以参数都会先被转成字符串
-
parseInt(27.2, 10)
:radix
如果不写,或者是0,默认是10。 所以parseInt('27.2', 10)
是整数27 -
parseInt(0, 1)
:radix
的范围是 2 -36(特殊情况除外), 1 不在范围内,所以 结果是NaN -
parseInt('0013', 2)
:radix
是2进制, 所以相当于把parseInt('001', 2)
准换为十进制 => 0✖️2^2 + 0✖️2^1 + 1✖️2^0 = 1 -
parseInt('14px', 3)
:radix
是3进制, 所以相当于把parseInt('1', 3)
准换为十进制 => 1✖️3^0 = 1 -
parseInt('123', 4)
:radix
是4进制, 所以相当于把parseInt('123', 4)
准换为十进制 => 1✖️4^2 + 2✖️4^1 + 3✖️4^0 = 27
总结
- 隐式转换: 字符串,布尔,null,undefined 基本数据类型转数字,步骤很简单。但是对象转数字,却要经过很多步骤,比如要经过
Symbol.toPrimitive
,valueOf
,toString()
- 显示转换,最主要的用途就是我们只取
数字
部分,当然取整数和浮点数,区别开方法即可。最重要的还有他的第二个参数radix
要掌握好 - 下一篇聊一聊其他数据类型的转换规则