['1','2','3'].map(parseInt) 的返回值是什么?

250 阅读2分钟

前言

这是一道前端面试题,看到这个问题第一反应结果是不是 [1,2,3],但是真正的结果是 [1, NaN, NaN],为什么呢?

Array.map()

map() 方法返回一个新数组,其结果是该数组中的每个元素都调用了所提供的函数后返回的结果

var arr = [1, 2, 3];
var arr1 = arr.map(x => x * 1);
console.log(arr1); // [1, 2, 3]

可以看出 map 方法中接受一个函数,用来遍历和处理数组中的每一个元素

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])

callback 一共可以接收三个参数:

  • 第一个参数 currentValue 是数组中正在处理的当前元素
  • 第二个参数 index 是数组中正在处理的当前元素的索引
  • 第三个参数 array 是当前调用 map 方法的数组

thisArg 可选,执行 callback 函数时使用的 this 的值

parseInt(string, radix)

radix 解析字符串的基数,基数规则如下:

  • 区间范围介于 2~36 之间
    // 将 '123' 看作 5 进制数,返回十进制数 38 => 1*5^2 + 2*5^1 + 3*5^0 = 38
    parseInt('123', 5);
    
  • 当参数为 0parseInt() 会根据十进制来解析
  • 若忽略该参数,默认的基数规则:
    • string0x 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数
      parseInt("0xf");  // 15 
      
    • string0 开头,其后的字符解析为八进制十六进制的数字
      // 0 * 8^1 + 8 * 8^0 = 8
      parseInt("08");   
      
    • string1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数
      parseInt("88.99f");   // 88
      
    • 只有字符串中的第一个数字会被返回
      parseInt("10.33"); // 10
      
    • 开头和结尾的空格是允许的
      parseInt(" 69 10 ");  // 69
      
    • 若字符串的第一个字符不能被转换为数字,返回 NaN
      parseInt("f");  // NaN  
      parseInt("f", 16);  // 15
      

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

['1', '2', '3'].map(parseInt)
// 相当于
['1', '2', '3'].map(function(cur, index){
  return parseInt(cur, index);
})

则代码执行如下:

parseInt('1', 0); // radix 为 0 时,使用默认的 10 进制  -> 1
parseInt('2', 1); // radix 值范围在 2-36,无法解析,超出区间范围  -> NaN
parseInt('3', 2); // radix 为 2,用 2 进制来解析,应以 0 或 1 开头,最大值小于 3,无法解析 -> NaN

因此最终结果是:[1, NaN, NaN]