爲何["1","2","3"].map(parseInt) 返回[1,NaN,NaN]?

在 javascript 中 ["1","2","3"].map(parseInt) 爲什麼​返回不是 [1,2,3] 倒是 [1,NaN,NaN]javascript

咱們使用進制的相關知識來解釋說明,若是你看完仍是沒有很清楚,能夠本身去了解一些進制的相關知識。java

咱們首先回顧一下 parseInt()map() 兩個函數的用法:數組

一、parseInt() 函數:

parseInt() 函數可解析一個字符串,並返回一個整數,可有兩個參數。瀏覽器

//語法:
parseInt(string, radix)
複製代碼
參數 描述
string 必需。要被解析的字符串。
radix

可選。表示要解析的數字的基數。該值介於 2 ~ 36 之間。bash

若是省略該參數或其值爲 0,則數字將以 10 爲基礎來解析。函數

一、當參數 radix 的值爲 0,或沒有設置該參數時,parseInt() 會根據 string 來判斷數字的基數。ui

當忽略參數 radix , JavaScript 默認數字的基數以下:this

(1)若是 string 以 "0x"或 「0X」 開頭,parseInt() 會把 string 的其他部分解析爲十六進制的整數。spa

(2)若是 string 以 0 開頭,那麼 ECMAScript v3 容許 parseInt() 的一個實現把其後的字符解析爲八進制或十六進制的數字。code

(3)若是 string 以 1 ~ 9 的數字開頭,parseInt() 將把它解析爲十進制的整數。

二、若是該參數小於 2 或者大於 36,則返回 NaN

提示和註釋

(1)只有字符串中的第一個數字會被返回。

(2)開頭和結尾的空格是容許的。

(3)若是字符串的第一個字符不能被轉換爲數字,則返回 NaN。

(4)在字符串以"0"爲開始時舊的瀏覽器默認使用八進制基數。ECMAScript 5,默認的是十進制的基數。

//當忽略參數 radix 
parseInt("10")//1*10^1+0*10^0=10  
parseInt("10.33")//1*10^1+0*10^0=10 
parseInt("34 45 66") //3*10^1+4*10^0=34 
parseInt(" 60 ") //6*10^1+0*10^0=60 
parseInt("40 years")  //4*10^1+0*10^0=40 
parseInt("He was 40")  //NaN 
parseInt("1f",16);		//1*16^1+f*16^0=16+15=31
parseInt("0x10")//1*16^1+0*16^0=16  string 以 "0x" 開頭,會把 string 的其他部分解析爲十六進制的整數 
parseInt("010")//0*10^2+1*10^1+0*10^0=10 或  0*8^2+1*8^1+0*8^0=8  string 以 0 開頭,舊瀏覽器默認使用八進制基數。ECMAScript 5,默認的是十進制的基數。

//當有參數 radix,表示以radix爲基數解析
parseInt("10",10) //1*10^1+0*10^0=10 
parseInt("10",8)//1*8^1+0*8^0=8
parseInt("10",16) //1*16^1+0*16^0=16複製代碼

咱們還須要瞭解進制數的相關知識:

二進制的定義:用0和1兩個數碼來表示的數。

三進制的定義:用0和1,2三個數碼來表示的數......

十進制的定義:用0和1,2,3...9十個數碼來表示的數。

十進制分別轉爲2、3、四進制的值
十進制 二進制 三進制 四進制
0 0 0 0
1 1 1 1
2 10 2 2
3 11 10 3
4 100 11 10
5 101 12 11
6 110 20 12
7 111 21 13
8 1000 22 20
9 1001 100 21
10 1010 101 22
//以2爲基數,
parseInt('1', 2)//1
parseInt('2', 2)//NaN
parseInt('3', 2)//NaN
parseInt('10',2)//2
//以3爲基數,
parseInt('1', 3)//1
parseInt('2', 3)//2
parseInt('3', 3)//NaN
parseInt('10',3)//3
//以4爲基數,
parseInt('1', 4)//1
parseInt('2', 4)//2
parseInt('3', 4)//3
parseInt('4', 4)//NaN
parseInt('10',4)//4
......

//總結:
咱們能夠這樣理解,二進制裏沒有2,3,...9,三進制裏沒有3,4...9,四進制裏沒有4,5...9
即當string沒法轉成radix基數時會返回NaN
複製代碼

由上可知,相關文檔只說明瞭兩種狀況會返回NaN,實際上還存在上面代碼的狀況:當string沒法轉成radix進制數時會返回NaN

可是爲何 ["1","2","3"].map(parseInt) 卻返回 [1,NaN,NaN]parseInt 須要 2 個參數 (val, radix), 而 map 傳遞了 3 個參數 (element, index, array)。

回到原題,作出解釋:

['1','2','3'].map(parseInt)
//  parseInt('1', 0) -> 1   //radix=0,以10爲基數解析 1*10^1+0*10^0=10
//  parseInt('2', 1) -> NaN //radix=1<2,返回NaN
//  parseInt('3', 2) -> NaN //3沒法轉成二進制

//即遍歷後結果爲 [1,NaN,NaN]
複製代碼

以上爲題的正解說明。

咱們接着來講map( )的用法:

二、map()方法:

對數組的每一個元素調用定義的回調函數並返回包含結果的數組。

//語法:
array.map(function(currentValue,index,arr), thisValue)
複製代碼
參數 描述
function(currentValue, index,arr)
必須。函數,數組中的每一個元素都會執行這個函數
函數參數:
參數 描述
currentValue
必須。當前元素的值
index
可選。當前元素的索引值
arr
可選。當前元素屬於的數組對象
thisValue
可選。對象做爲該執行回調時使用,傳遞給函數,用做 "this" 的值。
若是省略了 thisValue ,"this" 的值爲 "undefined"

返回值:其中的每一個元素均爲關聯的原始數組元素的回調函數返回值的新數組。

對於數組中的每一個元素,map 方法都會調用 callbackfn 函數一次(採用升序索引順序)。 不爲數組中缺乏的元素調用該回調函數。

下面的示例闡釋了 map 方法的用法:

// 定義回調函數
// 計算圓的面積
function AreaOfCircle(radius) { 
    var area = Math.PI * (radius * radius); 
    return area.toFixed(0); 
} 
// 定義一個數組,保護三個元素
var radii = [10, 20, 30]; 
// 計算 radii 的面積. 
var areas = radii.map(AreaOfCircle); // 314,1257,2827複製代碼

下面的示例闡釋thisValue參數的用法,該參數指定對其引用 this 關鍵字的對象,至關於給map的回調函數指定了this對象:

// 定義一個對象 object,保護 divisor 屬性和 remainder 方法
// remainder 函數求每一個傳入的值的個位數。(即除以 10 取餘數)
var obj = { 
    divisor: 10, 
    remainder: function (value) { 
        return value % this.divisor; 
    } 
} 
var numbers = [6, 12, 25, 30]; 

divisor = 6;
function remainder(value) {
return value % this.divisor;
}

numbers.map(obj.remainder, obj); //[6,2,5,0] obj.remainder this=obj
numbers.map(remainder, obj);//[ 6,2,5,0] window.remainder this=obj
numbers.map(remainder);//[0,0,1,0] window.remainder this=window 
numbers.map(obj.remainder);//[0,0,1,0] obj.remainder this=window 
//有兩個remainder函數,第一步肯定調用的是哪個,第二步肯定執行的時候this是誰複製代碼
從新定義 parseInt(string, radix) 函數:
var parseInt = function(string, radix) {
    return string + "-" + radix;
};
 
["1", "2", "3"].map(parseInt);//["1-0", "2-1", "3-2"]複製代碼
因而可知, map 函數將數組的值 value 傳遞給了 parseInt 的第一個參數,將數組的索引傳遞給了第二個參數。 第三個參數呢?咱們再加一個參數:
var parseInt = function(string, radix, obj) {
    return string + "-" + radix + "-" + obj;
};

["1", "2", "3"].map(parseInt);//["1-0-1,2,3", "2-1-1,2,3", "3-2-1,2,3"]
//"-" + obj 致使obj調用toString()方法自動轉換爲了string,至關於鏈接符
//第1次遍歷:1 + "-" + 0 + "-" + [1,2,3]="1-0-1,2,3"

//toString()還有如下幾種特殊狀況
[{a:1},{b:2}].toString()//"[object Object],[object Object]"
[1,2].toString()//"1,2"
[[1,2],[3,4]].toString()//"1,2,3,4"複製代碼
相關文章
相關標籤/搜索