大厂前端面试陷阱: map 与 parseInt 的奇妙碰撞

329 阅读3分钟

前言

在前端开发的面试中,经常会遇到一些看似简单,实则暗藏玄机的题目。其中, map 方法与 parseInt 函数的组合使用,就常常让不少求职者栽跟头。

问题

console.log(['1','2','3'].map(parseInt))

HR:请问这个输出什么?

我:这不就是一个简单的map函数吗,遍历字符串再转成数值类型。包输出1 2 3。

HR:回家吧孩子。

于是我连夜回去执行,发现是:1 NaN NaN

这是为啥啊?不符合逻辑啊???

我们不要寻求一步登天,来一步步分析。

Map

1. map 方法的工作机制

map 是数组的一个高阶函数,其功能是创建一个新数组,新数组中的每个元素都是原数组元素经过某种转换后得到的结果。它的语法如下:

const newArray = arr.map(callback(currentValue, index, array), thisArg);
  • 回调函数(callback):这是为数组每个元素执行的函数,该函数会返回一个新值,它可以接收三个参数:

    • currentValue:当前正在处理的数组元素
    • index:当前元素在数组中的索引
    • array:调用 map 方法的原始数组
  • thisArg(可选):在执行 callback 函数时使用的 this 值。

我们可以看到,map函数接收一个 回调函数(callback) 作为参数。这个回调函数会针对数组中的每个元素执行一次,然后返回一个新数组,新数组中的元素是原数组元素经过回调函数处理后的结果

那我们可以看到,这里的map接收了一个array的内置函数parseInt

ParseInt

  1. MDN 给出 parseInt 的官方定义是:parseInt(stringradix)  解析一个字符串并返回指定基数的十进制整数radix 是 2-36 之间的整数,表示被解析字符串的基数。

  2. 语法

parseInt(string, radix);
  1. 参数:
  • string:要被解析的值。如果参数不是一个字符串,则将其转换为字符串。字符串开头的空白符将会被忽略。

  • radix(可选):从 2 到 36 的整数,表示进制的基数

    例如指定 16 表示被解析值是十六进制数。如果超出这个范围,将返回 NaN。假如指定 0 或未指定,基数将会根据字符串的值进行推算。

  1. 返回值

(1)从给定的字符串中解析出的一个整数

(2)当出现以下任一情况时,返回NaN

  • radix 小于 2 或大于 36.
  • 第一个非空格字符不能转换为数字。

介绍完两种函数之后,我们再回头看看原题

题目详解

console.log( ['1','2','3'].map(parseInt) )

map 方法在调用 parseInt 时,会依次传入三个参数:当前元素、当前索引和原数组。而 parseInt 函数只接受两个参数:字符串和进制数。因此,实际的调用过程如下:

// map第一个参数传入的是字符串,第二个参数是进制数,第三个参数是原数组
// 所以 parseInt 会被执行三次,每次传入的参数分别是:
parseInt('1',0,['1', '2', '3']) 
parseInt('2',1,['1', '2', '3'])
parseInt('3',2,['1', '2', '3'])
// parseInt中第二个参数是进制数
  • 对于 parseInt('1', 0) ,当 radix 为 0 时, parseInt 会默认将其视为 10 进制,所以结果是 1。
  • 对于 parseInt('2', 1) ,由于 1 进制是不存在的,所以结果是 NaN 。
  • 对于 parseInt('3', 2) ,2 进制中只能出现 0 和 1,所以 3 无法解析,结果也是 NaN 。

如何避免陷阱

如果我们想要将数组中的字符串元素转换为整数,可以使用箭头函数来明确传递参数:

console.log(['1','2','3'].map(num => parseInt(num)));
// 输出 [1, 2, 3]

总结

通过这个例子,我们可以看到,在 JavaScript 中,看似简单的方法组合使用,可能会产生意想不到的结果。在面试和实际开发中,我们需要对这些细节有足够的了解,才能避免掉入陷阱。希望本文能帮助大家更好地理解 map 方法和 parseInt 函数的使用。