parseInt深度探究

最近在学js,偶然一次在浏览器中操作parseInt时,发现几个特别的情况,于是通过查阅相关文档,和不断的尝试,总结了对于parseInt的几个知识点。
paseInt的两种形式:
parseInt(value,index);
parseInt(value)
对这两种情况都做以分析

一、 对于只有一个参数的形式parseInt(value);

此方法针对value参数进行取整数部分的转换:
(1) 对于纯数字类型的value:
一般数字:
例如123,123.21。转换方式为取其整数部分即可。

parseInt(123);//--------返回结果:123
parseInt(123.21);//-------返回结果:123

以上只取了整数部分,不存在四舍五入。
对于特殊的数字类型:
例如0x11,对于这种进制数,先将其从对应进制转换为十进制,再对其结果进行取整。

parseInt(0x11);//--------返回结果:17

解析:0x11为十六进制数,16进制转10进制:
116的一次方 + 116的零次方 = 17;再对其取整,结果为17。

(2) 对于字符串类型value:
A. 若是纯数字型字符串,也是直接截取字符串中数字部分,遇到小数点停止截取,返回截取到的结果。若是符合进制数的类型,直接按照对应的进制转为十进制。(其实parseInt操作时在内部首先对要转换的数据先进行了转字符串的操作,后续有解释)。
例如:’123’,’123.23’,‘0x11’

parseInt('123'); //---------返回123
parseInt('12.323');//----------返回12
parseInt('0x11');//----------返回17

B. 若是数字与非数字组合,如果是字母打头,直接返回NaN,因为没有截取到数字部分,取不到整数,将返回NaN。如果是数字打头,截取数字部分,遇到非数字或者小数点停止截取,返回结果。
例如:’a123’ , ’1a23’ , ‘12a.3 ’ , ‘123.a1’,‘0a11’

parseInt('a123');//----------返回NaN
parseInt('1a23’);// ---------返回1
parseInt('12a.3');// ---------返回12
parseInt('123.a1');//----------返回123
parseInt('0a11');//-----------返回0

不论value是纯数字或者字符串,遵循截取value中的数字部分,遇到非数字或小数点停止截取,返回结果。


二、 对于含两个参数的形式parseInt(value,index);

重点部分:
第二个参数index指定了第一个形参value的进制类型,转换时通过此进制将value转换为10进制整数
parseInt 的转换机制:

(1) 对于字符串类型的value:

  • 非纯数字类型的字符串:

判断该字符串是否是以0x开头,如果是,进制index将被定义为16进制,再判断实参的index是否也为16进制,如果符合,就对其进行16进制转10进制的操作:
例如:’0x11’

parseInt('0x11',16);//--------返回结果17

但是存在如下情况

parseInt('0x11',18);//----------返回结果为0

为何会出现这种情况,猜测是在进制匹配上出现问题,因为0x开头,原本应为16进制转换,实参形参相统一时两者不匹配,按照实际所给的进制数进行匹配。那么存在一个进制合法性的问题,对于字符串’0x11’进行18进制的转换,要先对每个字符判断其合法性,第一个0符合,第二个x,问题就在此处,由于x不符合18进制,此处之后便不再判断,只保留了第一个的0,最终只返回结果0。
验证猜测:对’0e11’进行16进制和20进制的转换,

parseInt('0e11',16);//------返回3601
parseInt('0e11',20);//--------返回5621

分析:第0位符合条件,e被当作16进制中的14也符合条件,后两位均为1,也符合。计算方式:
14*16的二次方 + 1*16的一次方 + 1*16的零次方 = 3601;

再次验证反例,对’0e11’进行8进制转换,

parseInt('0e11',8);//---------返回0

原因也是在判断合法性上出了问题,8进制里没有e。
再例如:对’0b11’,进行12进制转换

parseInt('0b11',12);//---------返回1597(b在12进制里代表11)
parseInt('0b11',10);//---------返回0,原因10进制里没有b,不合法
  • 对于纯数字型的字符串:
    直接上例子:
parseInt('16',3);//----------返回1

按照一般思路:结果应该是1*3的一次方 + 6*3的零次方 = 9;

但是结果并非如此。 原因也是合法性的判断,对字符串中的每一位与其进制进行合法判断,第一个’1’符合3进制,第二个的’6’,3进制中只由0,1,2组成,逢三进一,逢不到6啊,这意味着什么,这意味着这一位不符合3进制,所以此处不合法,不再向后进行,只对第一个1进行转换,1结果还是1.

parseInt('16',8);//----------返回14
  //两个字符均符合8进制,返回结果就为8+6=14。

(2) 对于非字符串类型的value

A .符合0x开头的情况

判断该字符是否以0x开头,如果是以0x开头,例如0x11,先将其转换为字符串,然后对该字符串进行对应的16进制转10进制操作,然后在对结果进行对应实参进制数的转换,此处也要进行合法性的判断。
例如:

parseInt(0x11,16);------返回23

分析:

  1. 0x11先转换字符串,判断满足0x开头;
  2. 先对其进行16进制转10进制操作:1*16+1 = 17;
  3. 再对上述的结果,也就是17,进行对应实参(j就是第二个参数)进制数的转换,还是16进制,即对17进行16进制数的转换,依然先转字符串,然后判断每个字符是否符合进制的合法性,1和7均符合,最后进行16进制转10进制:
    1*16+7 = 23,最终结果23.

再举一个不合法的例子:

 parseInt(0xe1,4);------返回10;

分析:

  • 先转字串,满足0x开头。

  • 先对其进行16进制的转换,即14*16+1=225;

  • 在对上面的结果进行4进制转10进制的操作,先转字串,在判断每个字符的合法性,5不符合4进制,所以只对前两位也就是22进行4进制转十进制的操作。即2*4+2=10;

                 粗俗的理解:parseInt(0x11,16)进行的操作相当于:
                 parseInt((parseInt(‘0x11’,16)).tostring(),16)
    

符合0x开头的情况完结。

B .不符合’0x’开头的情况:

**对于纯是数字的:**先将其转为字符串,然后对每一位的字符进行进制的合法性判断,在此基础上再进行对应实参进制数的转换。
例如:

parseInt(17,8);//-------返回15
//分析:转为字符串后其中的1和7均符合8进制,
//再进行8进制转10进制的操作:1*8 + 7=15;

反例:

parseInt(17,6);//-------返回 1
//分析:转换为字符串后其中的1合法,但是7不符合6进制,
//最终只能对1进行6进制转换,最终结果返回1.

若是将反例中进制改为9进制

parseInt(17,9);//-------返回16
//转为字串后的俩字符都符合9进制,
//此处不再进行分析。

对于非纯数字的:转字符串后,不符合0x开头的,直接截取其数字部分,然后进行实参对应进制数的转换。
例如a0、0e0,1e0

parseInt(a0,16);//---------报错,因为..a0 is not defined,当成变量了
parseInt(0e0,16);//---------返回0
parseInt(1e0,16);//---------返回1,

分析:

  • 对于后两种为什么不报错,因为1e0,0e0这种形式的数字是一类科学计数法,可当作1*e的0次方,0*e的0次方。

再例如:

paesrInt(1e4,8);//--------返回4096

因为1e4被当作10000,相当于parseInt(10000,8);即8的四次方,所以结果为4096。


最后说一个特例:

 parseInt(null,24);//---------返回23,

相当的奇怪,是吧?
此处应该是只将n进行了识别,进制数为24时,可以识别到字母n,在0~9的基础上加上n在字母表中第14位,所以n会被返回23.当然也有合法性的判断,u排在第30位,此处就不合法了。
若改为:

parseInt(null,35);//--------返回1023631

计算方式:
n为第23位,u为第30位,l为第21位
23*35的三次方+30*35的平方+21*35+21 = 1023631
其转换原理与16进制相同。

最后,头一次写技术性博文,若有问题,希望前辈们指正。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值