这道题应该很多人都遇到过,我第一次做的时候最先想到的结果就是[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
但实际上结果是:
这时候就发现问题不对了,究其原因是翻译的有偏差,我们来看看 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]