- parseInt(string,radix)
用于将字符串转化为十进制数字,相比于Number()和一元+号来说,parseInt不是全量转化,举个例子:字符串'12px',用parseInt就是12,后两者是NaN
- 注意事项
-
- string如果是非字符串,会转化为字符串
- radix表示第一个参数的进制,具有自动推断能力,0x或0X开头的字符串 -> 16,其余默认是10,需要考虑进制范围:0,[2,32],否则返回NaN
- 自动过滤开头字符串
- 需要考虑正负号
- 第一个字符不能转数字直接返回NaN
- 代码实现
const myParseInt = (str, radix) => {
// 1. 校验第一个参数为字符串类型
if (typeof str !== 'string') str = str.toString() // 不考虑对象实现[Symbol.toPrimitive]
// 2. 过滤开头空格
str = str.trim()
// 3. 考虑正负号
let isPositive = true
if (str.startsWith('+') || str.startsWith('-')){
isPositive = str[0] === '+'
str = str.slice(1)
}
// 4. 自动推断:识别16进制
if (str.startsWith('0x') || str.startsWith('0X')){
str = str.slice(2)
if (!radix) {
radix = 16
} else if (radix !== 16){
return (radix >= 2 && radix <= 32) ? 0 : NaN
}
}
// 5. 校验第二个参数:范围、类型
if (!radix) radix = 10 // 0、undefined -> 10
if ((radix < 2 || radix > 32) || (typeof radix !== 'number')) return NaN
// 6. 任意进制 -> 10进制:利用ASCII码处理字母->数字
let res = 0
let isFirst = true // 校验首字符是否能转数字
for (let char of str) {
let code = char.charCodeAt(0)
if (char >= 'A' && char <= 'Z') {
code = code - 'A'.charCodeAt(0) + 10
} else if (char >= 'a' && char <= 'z') {
code = code - 'a'.charCodeAt(0) + 10
} else if (char >= '0' && char <= '9') {
code = code - '0'.charCodeAt(0)
} else {
// 不属于合法字符
if (isFirst) {
return NaN
} else {
break
}
}
// 校验进制
if (isFirst) {
isFirst = false
if (code >= radix) {
return NaN
}
} else {
if (code >= radix) {
break
}
}
res = res * radix + code
}
return isPositive ? res : -res
}
- 检验mdn测试用例:没问题!
console.log(myParseInt('123'));
// 123 (default base-10)
console.log(myParseInt('123', 10));
// 123 (explicitly specify base-10)
console.log(myParseInt(' 123 '));
// 123 (whitespace is ignored)
console.log(myParseInt('077'));
// 77 (leading zeros are ignored)
console.log(myParseInt('1.9'));
// 1 (decimal part is truncated)
console.log(myParseInt('ff', 16));
// 255 (lower-case hexadecimal)
console.log(myParseInt('0xFF', 16));
// 255 (upper-case hexadecimal with "0x" prefix)
console.log(myParseInt('xyz'));
// NaN (input can't be converted to an integer)
- 总结
-
- 第一大难点是两个参数的校验问题,需要考虑的边界case有点多,但理解了其实这些case都是可以考虑到的
- 第二大难点也是核心代码就是任意进制转10进制:其本质就是利用ASCII码表可以将字母转化成数字,再经过简单计算转化成与字母对应的10进制数字
- 上述代码基本上95%的测试用例都跟parseInt相符,剩下的5%我还没找出来
但归根结底应付面试我觉得足矣,况且我面试估计也写不出来,呜呜呜