Hello,大家好,我是 Sunday。
最近一个同学成功的拿到了某大厂 40 * 15 + 期权 offer
,总包算下来有 60W 多一点
这个成绩可以说非常的厉害了,总包在 我做的私教服务 中,已经接近最高的薪资了。
在跟该同学沟通面试问题的时候,有一个代码题让我印象比较深刻,面试官问:为什么['1 ','5','11'].map(parseInt)会返回[1, NaN, 3]
很有意思的问题对不对。所以,咱们今天这篇文章就来看看这个问题!
01:关于 map 函数
Array.prototype.map()
是 js 中的常用函数,我们通常会用它返回 新的元素组成的数组。
比如,我们希望返回所有元素的内容 * 2:
const arr = [1, 4, 9, 16];
const map1 = arr.map(x => x * 2); // [2, 8, 18, 32]
在这里,我们书写的 x => x * 2
代码,被称为 callbackFn
,即:回调函数。该回调函数可以写入 三个参数,即:
- element:数组中当前正在处理的元素
- index:正在处理的元素在数组中的索引
- array:调用了 map() 的数组本身
只不过,通常情况下,我们使用 map
时,只会使用回调函数的第一个参数(少数情况下会用到第二个)。
但是,当我们在 map
中使用 parseInt
时,情况就不同了。
我们先做一个简单的实验:
// 注意:这里传递的是 console.log 的引用,而不是执行的结果
['1', '5', '11'].map(console.log)
大家角色这样的代码打印出来的结果是多少?我们来看看,它一定会让大家觉得奇怪:
// 输出
1 0 [ '1', '5', '11' ]
5 1 [ '1', '5', '11' ]
11 2 [ '1', '5', '11' ]
刚看到这样的代码,大家可能会认为非常的奇怪,甚至有点看不懂 ['1', '5', '11'].map(console.log)
在描述什么。
所以,我们把这个代码改写一下:
// 等同于 ['1', '5', '11'].map(console.log)
['1', '5', '11'].map((element, index, array) => {
return console.log(element, index, array)
})
因为,我们传入的 console.log
是函数的引用(等同于 () => xxx
),那么此时 callbackFn
的三个函数,都会传递到 console.log
之中,最终就如以上代码所示。
02:代码题:['1','5','11'].map(parseInt) 原理
那么明白了上面的问题之后,咱们再来看 ['1','5','11'].map(parseInt)
,按照我们刚才的解释,这个代码可以被解析成如下内容:
['1', '5', '11'].map((element, index, array) => {
return parseInt(element, index, array)
})
如果我们使用变量 res
接收 map
的返回值,打印之后就是 [ 1, NaN, 3 ]
。
为什么呢?我们来解析一下。整个 map
会循环三次:
- 第一次:
parseInt('1', 0, ['1', '5', '11'])
- 第二次:
parseInt('5', 1, ['1', '5', '11'])
- 第三次:
parseInt('11', 2, ['1', '5', '11'])
他们的打印结果分别为:
- 第一次:1
- 第二次:NaN
- 第三次:3
那么,此时就有同学奇怪了,为什么 parseInt('5', 1, ['1', '5', '11'])
和 parseInt('11', 2, ['1', '5', '11'])
他们的返回结果会是 NaN
和 3
呢?
那么,咱们就来看看 parseInt 都做了什么吧
03:关于 parseInt 函数
parseInt
其实接受两个参数,咱们主要看 第二个参数:
- string:要被解析的值
- radix:从 2 到 36 的整数,表示进制的基数。如果不再这个范围,则返回
NaN
。如果是 0 ,则表示未指定,基数将会根据字符串的值进行推算(在当前场景下,会被作为10
进制)
那么现在大家明白了。
- 第一次:
radix
为 0 ,表示 10 进制,所以parseInt('1', 0)最后一个省略
返回1
- 第二次:
radix
为 1 ,不在 2-10 的范围内,所以parseInt('5', 1)
返回NaN
- 第三次:
radix
为 2 ,表示 2 进制,所以parseInt('11', 2)
中的 11 被作为 2 进制 ,返回的是 10 进制的结果。即:2进制的 11 转化为 10 进制为3
总结
以上就是 为什么['1','5','11'].map(parseInt)会返回[1,NaN,3]
所有解释。如果大家也在面试中遇到了这个问题,那么可以分别从
map
的执行逻辑parseInt
的执行逻辑
两方面进行解释。
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的
offer
。 已帮助数百位同学拿到了中大厂offer
。