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

这道题应该很多人都遇到过,我第一次做的时候最先想到的结果就是[1,2,3],但是又觉得不会这么简单,最后验证时果然答错了。我也看过相关解答,但总觉得说的不太清晰,或者似懂非懂的,所以不妨来认真看一下。

parseInt

这是开发中特别常用的一个api,作用是将传入的参数转换为整数,例如:

parseInt('10string') = 10
parseInt(10.233) = 10

通常我们会这么使用它,但它其实还可以传入第二个参数,我们来看 MDN 上对它的定义:

parseInt(string, radix) 将一个字符串 string 转换为 radix 进制的整数, radix 为介于2-36之间的数。

按照这个定义来使用的话,它的效果应该是这样的:

// 按照定义,将 ‘5’ 转换为 2 进制的整数
parseInt('5',2) = 101

但实际上结果是:


image.png

这时候就发现问题不对了,究其原因是翻译的有偏差,我们来看看 MDN 英文原版是怎么定义的:

The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).

大致意思是:parseInt()函数解析字符串参数,并返回指定基数(数学数字系统中的基数)的整数。

看到这里其实还没有说明白这个radix参数到底是怎么作用的,我又查了W3school上的定义是:parseInt() 函数可解析一个字符串,并返回一个整数,这个也没说明白。其实只看定义确实看不明白的,但是如果看一些示例的话,或许就明白了,下面这是一些例子:

parseInt("10");         //返回 10
parseInt("19",10);      //返回 19
parseInt("11",2);       //返回 3
parseInt("17",8);       //返回 15
parseInt("1f",16);      //返回 31

这下,你看明白了吗?我也不啰嗦了,这个radix参数的作用应该是:当radix参数为 n 时,将会把第一个参数看作是一个数的 n 进制表示,而返回的值则是十进制数。例如:

parseInt('123',4) // 将 '123' 看作是4进制数,返回十进制数 27 => 1*4^2 + 2*4^1 + 3*4^0  = 27

搞明白了第二个参数的作用,我们来看看parseInt的一些规定。

我们平时使用parseInt时一般不指定第二个参数,当第二个参数为undefined,或者为0,或者没有指定的情况下,JavaScript作如下处理:

  • 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制);
  • 如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决定。ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值;
  • 如果字符串 string 以其它任何值开头,则基数是10 (十进制).

以上资料来源于 MDN。另外,如果第一个参数不能被转换成数字,parseInt就返回NaN

map

map也是常用的api,map()方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果,说得太拗口,举个简单的例子:

const arr = [1, 2, 3]
// 返回新数组,数组的每一项值是原始数组的项值加上索引的和
const newArr = arr.map((item, idx) => {
  return item + idx
}) 
console.log(newArr)  // [1,3,5]

map()方法中的回调函数是有三个参数的,通常我们只需要使用前两个,就像上面例子一样。完整的回调函数参数如下:

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

// currentValue:callback 数组中正在处理的当前元素(必须)
// index:callback 数组中正在处理的当前元素的索引(非必须)
// array:map 方法调用的数组(非必须)
// 还有 thisArg,是执行 callback 函数时值被用作this,非必须,了解下即可

再看原题

结合这两个知识点再来看原题:

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

parsetInt 在这里就相当于map()方法的回调函数,实际的执行代码相当于这样:

['1', '2', '3'].map((item, idx) => {
  return parseInt(item, idx)
})

再结合parseInt的特性,它的返回值是这样的:

parseInt('1', 0)  // 返回 1,基数为 0 时,以 10 进制表示 '1',返回 10 进制
parseInt('2', 1)  // 返回 NaN,基数范围是 2-36,解析失败,返回 NaN
parseInt('3', 2)  // 返回 NaN,二进制表示的数只能含 0 和 1,3 不是二进制表示,解析失败,返回NaN

所以这道题的最终结果是:

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

写在结尾

再遇到此类题目你会做了吗?不妨自行测试一下这题:

['10','10','10','10','10'].map(parseInt)

另外,原题想要的结果是希望将数组里每一项的字符串都转换为数字,显然使用parseInt是不行的,那么该怎么实现需求呢?答案就是使用Number,如下:

['1', '2', '3'].map(Number) = [1, 2, 3]

你可能感兴趣的:(['1', '2', '3'].map(parseInt) = ?)