前言
之前碰到一道题如下:
var arr = ['1','2','3','4','5','6']
var newArr = arr.map(parseInt) //newArr是多少?
第一眼看到题目会很肯定答案是[1,2,3,4,5,6],然而到控制台跑完后发现结果是:
[1,NaN,NaN,NaN,NaN,NaN] //什么鬼?
这就牵涉到parseInt()方法究竟做了什么了?
解答
查询MDN发现是这样介绍的:
parseInt() 函数解析一个字符串参数,并返回一个指定基数的整数 (数学系统的基础)。
指定基数!没错这就是出现上述结果的原因。完整的parseInt()发法的调用方式应该如下:
parseInt(string, radix);
string
要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。
radix
一个介于2和36之间的整数(数学系统的基础),表示上述字符串的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。始终指定此参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当未指定基数时,不同的实现会产生不同的结果,通常将值默认为10。
也就是说我们平时使用的
parseInt('100')
等价于
parseInt('100',10)
一些radix的使用例子如下:
eg:
//expression below will return 15
parseInt("0xF", 16);
parseInt("F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt(015, 10);
parseInt("015", 10);
parseInt(15.99, 10);
parseInt("15,123", 10);
parseInt("FXX123", 16);
parseInt("1111", 2);
parseInt("15 * 3", 10);
parseInt("15e2", 10);
parseInt("15px", 10);
parseInt("12", 13);
回到题目,我们在使用map方法时,使用了参数element(代表数组的每一个成员)和index(下标)可以把代码转为如下:
var arr = ['1','2','3','4','5','6']
var newArr = arr.map((ele,index) =>parseInt(ele,index))
这样一来结果也就好解释了,值得一提的是当radix为0时会得到和10一样的结果,所以第一个值为1,后面radix为1只会得到NaN,而为2、3、4、5、6时每一位的数不可以等于进制数,所以得到的都是NaN,所以得到结果为:
[1,NaN,NaN,NaN,NaN,NaN]
其他
ECMAScript 5 移除了八进制解析
ECMAScript 5 规范不再允许parseInt函数的实现环境把以0字符开始的字符串作为八进制数值。ECMAScript 5 陈述如下:
根据给定radix,parseInt函数产生一个由字符串参数内容解析过来的整数值。字符串中开头的空白会被忽略。如果radix没有指定或者为0,参数会被假定以10为基数来解析,如果数值以字符对0x或0X开头,会假定以16为基数来解析。
简单点说:
//ES5以前
parseInt('012') //以前会按8进制转为10进制得到10
//ES5以后
parseInt('012') //12
//值得注意的是
parseInt(012)// 10,当是number时还是按8进制转为10
这与ECMAScript 3有所不同,ECMAScript 3仅仅是不提倡这种做法但并没有禁止这种做法。
总结
- parseInt()有string和radix两个入参,入参不同得到的结果不同
- ES5以后以0开头的8进制字符串在不知道radix的情况下不会按8进制解析