大厂面试代码题:为什么['1','5','11'].map(parseInt)会返回[1,NaN,3]

13,125 阅读5分钟

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,即:回调函数。该回调函数可以写入 三个参数,即:

  1. element:数组中当前正在处理的元素
  2. index:正在处理的元素在数组中的索引
  3. 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']) 他们的返回结果会是 NaN3 呢?

那么,咱们就来看看 parseInt 都做了什么吧

03:关于 parseInt 函数

parseInt 其实接受两个参数,咱们主要看 第二个参数

  1. string:要被解析的值
  2. 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] 所有解释。如果大家也在面试中遇到了这个问题,那么可以分别从

  1. map 的执行逻辑
  2. parseInt 的执行逻辑

两方面进行解释。

前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer 已帮助数百位同学拿到了中大厂 offer