面試時經常會問到關於['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。