前言
开始是由一道笔试题引起的思考,问:
["1", "2", "3"].map(parseInt);的返回结果是?
原因是map的回调函数传入了三个参数,也就是说parseInt调用其实是这样的: parseInt(item, index, array);
而parseInt
只接收两个参数,第三个被忽略,第二个是进制。所以parseInt('2', 1); parseInt('3', 2);
都返回了NaN,而parseInt('1', 0);
返回了1,是因为传入0进制是无效的,最终会按10进制处理。
其实我理解的进制,其实就是一个有效数字范围而已,2进制的有效范围为0,1所以有:
image.png可以看到'2'属于无效的。
正文
基于这个理解,下面贴出原生实现parseInt
方法,自己实现一遍的确有点蛋疼,但它能让你真正的理解parseInt
。并且在一次面试中面试官就要求手撕 parseInt
,当时是磕磕绊绊写出来了,回去后对细节都进行处理,各种刁钻输入都和原生parseInt
结果一样:
function myParse(data, radix = 10) {
if (radix > 36 || radix < 2 || !Number.isInteger(radix)) { // 进制必须是大于等于2和小于等于36的整数
return NaN;
}
if (radix === 0) {
radix = 10;
}
let str = data.toString().toLowerCase(); // parseInt本质就是字符串转整数,即使你输入的是数字,也会先给你转为字符串
for (var i = 0; i < str.length; i++) { // 找出进制内有效的字符,直到遇到无效字符为止
let char = str[i];
// 要区分 是 0-9 或者是 a-z 并且属于合法范围
if (/[0-9]/.test(char)) {
if ((char | 0) >= radix) {
break;
}
} else if (/[a-z]/.test(char)) {
if (char.charCodeAt() - 86 > radix) {
break;
}
} else {
break;
}
}
let validStr = str.substr(0, i);
let len = validStr.length;
if (len === 0) {
return NaN;
}
let res = 0;
for (let i = 0; i < len; i++) { // 对有效字符进行计算
let n = 0;
let char = validStr[i];
if (/[0-9]/.test(char)) {
n = char | 0;
} else { // 如果是字母
n = char.charCodeAt() - 87; // 这公式刚好对应,a 对应 10,b 对应 11...,z 对应 35
}
res += n * (radix ** (len - i - 1));
}
return res;
}
console.log(myParse(1/0, 19));
console.log(myParse(0.000008));
console.log(myParse(false, 16));
console.log(myParse(103, 2));
console.log(myParse(new String(42), 2));
自己实现的parseInt
image.png
更进一步
本来问题到这里就解决了,但我想,'2'无法使用1进制表示,所以parseInt('2', 1)
为NaN
。所以那么0可以吗,我试了一下:parseInt('0', 1);
也是NaN
。
一进制是存在的,但是竟然没有一个数字能用一进制来表示?0也不可以。
这好像是数学问题了。
要表示一个自然数N,我们得先选用一个符号来代表1,然后将之重复N次。举例来说,使用 | 作为符号,数字5则以|||||表示。就好像数手指一样,一根手指就为1。
想想也是,如果用0表示的话,00000应该就是5,但是计算
0⋅Math.pow(1, 5) + 0⋅Math.pow(1, 4) + 0⋅Math.pow(1, 3) + 0⋅Math.pow(1, 2) + 0⋅Math.pow(1, 1)
的结果是0,这显然矛盾。
所以,记住parseInt的进制有效输入是整数2~36,如果输入了0,则会按照10进制处理。而其他进制都返回了NaN。
image.png参考链接:
["1", "2", "3"].map(parseInt)为什么结果是[1, NaN, NaN]
What would base 1 be?
网友评论