看到这样一道题目: ['1','2','3'].map(parseInt)
执行结果是什么?为什么?
执行结果是:
[1, NaN, NaN]
我们将题目的代码转换一下:
['1','2','3'].map((item,index)=>{
return parseInt(item,index);
})
相当于:
parseInt('1', 0); // 1 why??
parseInt('2', 1); // NaN why??
parseInt('3', 2); // NaN why??
带着思考我们来扩展下 parseInt
的知识点。
parseInt(str[,radix])
能够将一个字符串数值转换为 radix
进制的整数。【See MDN】
参数: str
如 str 不是字符串,则先将其转为字符串,通过 ToString 抽象操作
进行转换,字符串开头的空格将会被忽略。
参数: radix
radix 取值范围是 2~36,默认是 10,建议使用的时候明确指定。
返回值
返回解析后的结果,如果被解析参数的第一个字符
无法被转换成数值类型,则返回 NaN
。radix
(例如n) 参数会把 str
当作是这个数的 n 进制表示,返回结果是10进制。
例如:
parseInt('023',8) //将 '023'看作是8进制数,返回10进制数:0x8^2+2x8^1+3x8^0 = 19
示例一:
parseInt('1',0) // 1
parseInt('012') // 12 似乎和以下的规则3有矛盾,这里暂时不知道原因,当然不建议这么写
parseInt('0x12') // 18
当 radix 为0或者没有设置时,parseInt会根据 str 来判断基数。
示例二:
parseInt('2',1) //NaN 其中1不在2~36范围内
parseInt('3',2) //NaN 除'1','0'外,其他均不能用来表达二进制数
示例三:
parseInt('0xF',16) //15 F 用10进制表示是15
parseInt('F',16) //15
示例四:
parseInt('17', 8) //15 1x8^1+7x8^0 = 15
parseInt(021, 8) //15 021是非字符串,首先通过ToString转换成 '17',再转换成10进制。
示例五:
parseInt(0.00000000000434, 10) //4 非常小的数,会忽略掉前面的0,保留剩下的第一个数值
parseInt(0.00000100000434, 10) //0
parseInt(0.00000010000434, 10) //1 小数点7位之后会认为是非常小的数
parseInt(4.7 * 1e22, 10) // 4 非常大的数,忽略第一位之后的
我们可以看到 parseInt 有时候的转换不如预期,规则也很多,因此在实际的开发过程中需要更加严格的校验。可以使用lodash的parseInt或者封装一个(摘抄自MDN):
// 通过正则来严格匹配
let filterInt = function (value) {
if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))
return Number(value);
return NaN;
}
console.log(filterInt('421')); // 421
console.log(filterInt('-421')); // -421
console.log(filterInt('+421')); // 421
console.log(filterInt('Infinity')); // Infinity
console.log(filterInt('421e+0')); // NaN
console.log(filterInt('421hop')); // NaN
console.log(filterInt('hop1.61803398875')); // NaN
console.log(filterInt('1.61803398875')); // NaN