parseInt第二个参数学习
parseInt语法: parseInt(string, radix)
之前使用parseInt的时候,大部分都是使用的第一个参数
比如:
parseInt(10.1) // 10
parseInt('5a') // 5
parseInt('2') // 2
今天看到一道面试题,内容为
["1", "2", "3"].map(parseInt)
其解释为:
首先, map接受两个参数, 一个回调函数 callback, 一个回调函数的this值
其中回调函数接受三个参数 currentValue, index, arrary;
而题目中, map只传入了回调函数--parseInt.
其次, parseInt 只接受两个两个参数 string, radix(基数).
在没有指定基数,或者基数为 0 的情况下,JavaScript 作如下处理:
如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制).
如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决- 定。ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值。
如果字符串 string 以其它任何值开头,则基数是10 (十进制)。
所以本题即问
parseInt('1', 0);
parseInt('2',1);
parseInt('3', 2);
首先后两者参数不合法.
所以答案是[1, NaN, NaN]
对于前面的说明还是比较理解的,但是对于parseInt第二个参数的说明就不是很理解了,所以在网上找了一些资料后加深了对该参数的理解。
我们知道,parseInt方法当第二个参数不写时,函数会尝试逐个解析字符串中的字符,直到遇上一个无法被解析成数字的字符,然后返回该字符前所有数字字符组成的数字。但是第二个参数加上后,结果则可能会完全不一样。
对于第二个参数,MDN上的解释是
一个2到36之间的整数值,用于指定转换中采用的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。总是指定该参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当忽略该参数时,不同的实现环境可能产生不同的结果。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
注:ES5已经规定了如果省略第二个参数就代表用十进制解析。
所以对于第二个参数的理解,其实就可以理解为"进制",比如第二个参数为2,则为二进制,3则为三进制,16则为十六进制等等。
而我们进制的计算公式为:
xyz(n) = x*n^2 + y*n^1 + z
比如二进制:
12 = 5
计算方法:1*2^1 + 2*2^0 = 5
三进制
21 = 7
计算方法:2*3^1 + 1*2^0 = 7
那么对于上面的问题就比较好理解了
parseInt('1',0); // 十进制,结果则为1
parseInt('2',1); // 一进制,最大为0,那么2就会不被解析,那就会变成NaN
parseInt('3',2); // 二进制,最大为1,那么3就会不被解析,那就会变成NaN
特别说明
我们前面用到的radix
全部都是10以内的,那么最大就是十进制时的数字9,我们知道,radix
的范围是2~36,在解析的过程中遇到无法被解析成数字的字符,就会返回该字符前所有数字字符组成的数字,那么当radix
大于10的时候呢?这个时候就会和前面有所差异了,比如radix为11,即十一进制时,最大的数字就变成了两位数,这样肯定是不行的,所以从10以后,就开始用字母代替,比如 a = 10,b = 11,c = 12,...z=35
,这也就能解释为什么radix
的范围是2~36
了。
所以:parseInt('dasff66',16) 的结果是多少呢?
在16进制中,最大的数字是15,对应字母也就是f,超过f的字母也就超出了16进制的解析范围。
'dasff66'的第一个字符是d,也就是十进制中的13,第二个字符是a,也就是十进制10,第三个字符s,代表十进制中的28,这显然超出了16进制的解析范围,所以s和它之后的字符都会被parseInt自动忽略,所以我们得到结果为:
13 * 16^1 + 10 * 16^0 = 218
至此,对于parseInt的第二个参数已经有了全面的了解,后面再遇到类似的问题也能够有明确的解题思路了。
PS:注意下,另一个函数parseFloat只接受一个参数,只能使用十进制去解析。