写在前面
我们都知道parseInt
可以将字符串转换成数字。那它和Number
转换有什么区别吗?我们从一组例子来看:
var a = '42'
var b = '42px'
Number(a) //42
parseInt(a) //42
Number(b) //NaN
parseInt(b) //42
解析允许字符串中含有非数字字符,解析从左到右的顺序,如果遇到非数字字符就停止。而强制类型转换不允许出现非数字字符,否则会失败,并返回NaN
。
看看定义
parseInt(string, radix)
: 解析一个字符串并返回指定基数的十进制整数。
radix
是 2-36 之间的整数,表示被解析字符串的基数。 假如指定 0
或未指定,基数将会根据字符串的值进行推算
需要注意的返回NaN
的情况:
- 当
radix > 36
或者radix < 2
- 第一个非空格字符不能转换为数字
特殊情况:
- 如果输入的
string
以0x
或0X
(一个 0,后面是小写或大写的 X)开头,那么 radix 被假定为 16,字符串的其余部分被当做十六进制数去解析 - 如果输入的
string
以 "0
"(0)开头,radix
被假定为8
(八进制)或10
(十进制)。具体选择哪一个 radix 取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),但不是所有的浏览器都支持。因此,在使用parseInt
时,一定要指定一个 radix - 如果输入的
string
以任何其他值开头,radix
是10
(十进制) - 如果字符串里有空格,
parseInt
允许前导和尾随空格
来看看正常的用法
parseInt('123', 5) // 1 * 5^2 + 2 * 5 + 3 * 5^0 = 38
parseInt("0xF", 16) // 15
parseInt("F", 16) // 15
parseInt("17", 8) // 15
parseInt("015", 10) // 15
parseInt(15.99, 10) //15
parseInt("15,123", 10) //15
parseInt("1111", 2) // 15
parseInt("15 * 3", 10) // 15
parseInt("15e2", 10) // 15
踩坑一:如果parseInt的参数不是字符串,则会先转为字符串再转换
parseInt(021, 8)
parseInt(015, 8)
先自己算算看,这两个答案多少?
答案是:17, 11。
有没有被这个答案惊到呢。这里面有个坑:如果parseInt的参数不是字符串,则会先转为字符串再转换,所以对上述的例子来说, 021
会首先转换成string ---> '17'
, 所以parseInt(021, 8)
等价于 parseInt('17', 8)
,即: 1 * 8 + 7 * 8^0 = 15
。同理, parseInt(015, 8)
等价于parseInt('13', 8) = 11
踩坑二:科学计数法
parseInt(0.000008) // 0
parseInt(0.0000008) //8 (8e-7)
parseInt(800000000000000000000) // 800000000000000000000
parseInt(8000000000000000000000) // 8 (8e21)
当小数点后0
的个数小于或者等于5个0时,以字面量的形式表示,当大于5个0时,用科学计数法表示;而当小数点前的位数
小于或者等于21时,采用的是字面量,当大于21位时,用科学计数法表示。
踩坑三: 截断操作
parseInt('42px') // 42
parseInt(false, 16) //250
这里就回到了文章最开始提到的例子啦~ 为啥parseInt('42px')
,里面有无效数字字符还是可以转换成数字,就是parseInt
它有个截断操作,当它在解析的过程中遇到不是有效的数字字符,它的解析就会就此停止。因此parseInt('42px')
,当它解析过程中遇到p
时就停止了。而对于另一个例子来说,它radix
的值为16,按照一个16进制来解析,只能解析fa
,l
已经超出16进制的表示数,因此停止,parseInt(false, 16)
等价于parseInt('fa', 16) ==> 15 * 16 ^ 1 + 10 * 16^0 = 250
踩坑四: 特殊值
parseInt('34', 2) // NaN, 字符超出2进制的表示范围
parseInt('103', 2) // 2 = 1 * 2^1 + 0 * 2^0 , 3超出范围,解析停止
parseInt(011, 2) // NaN
这里讲一下第3个例子,其实前面踩坑一中提到了,对于011
,parseInt会先把它转换成字符串,而011
是个八进制的表示数,所以,在变成字符串后变成了'9'
,即parseInt(011, 2)
等价于parseInt('9', 2)
,而9
是超过了2进制的表示范围的 ==> NaN
parseInt(1/0, 19) // 18
这题我自己捋了一下的:
首先1/0
,这个值肯定是个无穷大,js会把这个值toString
的时候变成Infinity
,所以呢,这题就变成了:parseInt('Infinity', 19)
,对于19进制的数来说,表示范围为: 0~9
,a~i
。解析的时候只能解析到开头的I
,对基数19的数来说,I
即为 18
。
踩坑五: 面试题
听说有个面试题比较坑,也整理了进来:
[1,2,3].map(parseInt())
说这个题之前,要先回忆下map
,对这一题来说,map
是略写了而已,我们把这个题写全就会变得很清晰:
[1,2,3].map(parseInt) ==> [1,2,3].map((item, index) => { parseInt(item, index)) })
=>
parseInt(1, 0) // 1
parseInt(2, 1) // NaN
parseInt(3, 2) // NaN
结言
结束了,hhh,对面试还是有点用的,大家可以了解一下。