常见面试题——['1','2','3'].map(parseInt)
面试时经常会问到关于['1','2','3'].map(parseInt)的问题,很多时候回答的仅仅就是一个正确的答案,对于更深入的原理却并不怎么了解,下面就对该问题做一下详解。
面试经常会问:
1 ['1','2','3'].map(parseInt)
上述问题的答案是什么?对此,先不来探讨这个题的答案是什么,从后面的解释中一步步得到答案,先认识一下 parseInt() 函数,parseInt() 函数解析一个字符串参数,并返回一个指定基数的整数
语法:
1 let m = parseInt( string[, radix] );
string:要被解析的值。若参数不是字符串,则会被隐式转换成字符串( toString()方法 )。字符串开头的空白符将会被忽略。
radix:一个介于2和36之间的整数(不包含36),表示上述字符串的基数。默认为10。返回值:返回一个整数或者NaN(基数就是类似的进制数)(特别的:当radix为0时会当做默认10进制处理)。
个人理解:parseInt函数会根据基数的值去解析字符串,其中基数类似进制数,(如:2进制:0,1,遇2进1;3进制:0,1,2,遇3进1 ...)解析时会忽略掉字符串中比进制数大的数(若忽略完了就解析空字符串,即NaN)
栗子:
1 parseInt(100,3) // (1*3^2)+(0*3^1)+(0*3^0) = 9 2 3 parseInt(15,3) // 会忽略比3大的数5,直接解析数字1,即(1*3^0) = 1 4 5 parseInt(6,3) // 忽略比3大的数字6,解析空字符串,即 NaN 6 7 parseInt(250,3) // 忽略比3大的数字5,且数字5后面的也会被忽略,2*3^0 = 2
扩展:基数(radix)的范围为什么会是 2~36(不包含36)?我们都知道进制数中最小为2进制,对于16进制来说,数字10以上就只能用字母表示,即:a = 10,b = 11,c = 12,...,z = 35,所以基数的最大值为35。
补充:和 parseInt 类似的另一个方法 parseFloat 则没有这么复杂了,解析时只会按照十进制方式解析字符串。
注意:在 radix 为 undefined,或者 radix 为 0 或者没有指定的情况下,js机制会做以下处理:
- 若字符串 string 以" 0x " 或 " 0X "开头,则基数为16(十六进制)
- 若字符串 string 以" 0 "开头,则基数是8(八进制)或者10(十进制),具体采用哪个是由当时环境决定,ECMScript 5 规定使用10,但不是所有浏览器都遵循该规定,故遇到该情况时需要给定 radix 值
- 若字符串 string 以其他任何值开头,则基数是10(默认十进制)
接着再来介绍一下 map() 方法,map() 方法创建一个新的数组,其结果是该数组中的每个元素都调用一个提供的函数(callback)后返回的结果。
let newArray = arr.map(function callback( currentValue[,index[, array]] ){ // return element for newArray }[, thisArg])
根据上述语法可以看到 callback 回调函数需要三个参数,实际中通常只使用第一个参数(其他两个参数是可选的)。currentValue 是 callback 数组中正在处理的当前元素。index可选,是 callback 数组中正在处理的当前元素的索引。array 可选,是 callback map 方法被调用的数组。另外还有 thisArg 可选,是执行 callback 函数时使用的 this 值。
let arr = [ 3,4,5 ]; let newArray = arr.map( (num)=>num+1 ); console.log( newArray ); // [ 4,5,6 ]
在 [ '1', '2', '3' ].map( parseInt )例子中,对于每个迭代 map,parseInt 会传递两个参数:字符串和基数。所以实际上执行的代码为:
1 ['1', '2', '3'].map( (item,index)=>{ 2 console.log( item,index ) 3 return parseInt( item,index ) 4 }) 5 6 /* 7 打印的结果为: 8 '1' 0 9 '2' 1 10 '3' 2 11 */ 12 13 /* 14 返回值 15 parseInt( '1', 0 ) 16 parseInt( '2', 1 ) 17 parseInt( '3', 2 ) 18 */
所以最终 [ '1', '2', '3' ].map( parseInt )的结果为 1 NaN NaN。