為什麼 ["1", "2", "3"].map(parseInt) 返回 [1,NaN,NaN]?
在 javascript 中 ["1","2","3"].map(parseInt) 為何返回不是 [1,2,3]
卻是 [1,NaN,NaN]
?
我們首先回顧一下 parseInt()
個 map()
兩個函式的用法:
parseInt() 函式
定義和用法
parseInt()
函式可解析一個字串,並返回一個整數。
語法
parseInt(string, radix)
引數 | 描述 |
---|---|
string | 必需。要被解析的字串。 |
radix |
可選。表示要解析的數字的基數。該值介於 2 ~ 36 之間。 如果省略該引數或其值為 ‘0‘,則數字將以 10 為基礎來解析。如果它以 ‘”0x”‘ 或 ‘”0X”‘ 開頭,將以 16 為基數。 如果該引數小於 2 或者大於 36,則 ‘parseInt()‘ 將返回 ‘NaN‘。 |
返回值
返回解析後的數字。
說明
當引數 radix
的值為 0
,或沒有設定該引數時,parseInt()
會根據 string
來判斷數字的基數。
舉例:
-
如果
string
以"0x"
開頭,parseInt()
會把string
的其餘部分解析為十六進位制的整數。 -
如果
string
以0
開頭,那麼 ECMAScript v3 允許parseInt()
的一個實現把其後的字元解析為八進位制或十六進位制的數字。 -
如果
string
以 1 ~ 9 的數字開頭,parseInt(
將把它解析為十進位制的整數。
提示和註釋
註釋:只有字串中的第一個數字會被返回。
註釋:開頭和結尾的空格是允許的。
提示:如果字串的第一個字元不能被轉換為數字,那麼 parseInt()
會返回 NaN
。
例項
在本例中,我們將使用 parseInt()
來解析不同的字串:
parseInt("10"); // 返回 10 (預設十進位制)
parseInt("19",10); // 返回 19 (十進位制: 10+9)
parseInt("11",2); // 返回 3 (二進位制: 2+1)
parseInt("17",8); // 返回 15 (八進位制: 8+7)
parseInt("1f",16); // 返回 31 (十六進位制: 16+15)
parseInt("010"); // 未定:返回 10 或 8
map 方法
對陣列的每個元素呼叫定義的回撥函式並返回包含結果的陣列。
array1.map(callbackfn[, thisArg])
引數 | 定義 |
---|---|
array1 | 必需。一個數組物件。 |
callbackfn | 必需。一個接受**最多**三個引數的函式。對於陣列中的每個元素,‘map‘ 方法都會呼叫 ‘callbackfn‘ 函式一次。 |
thisArg | 可選。可在 ‘callbackfn‘ 函式中為其引用 ‘this‘ 關鍵字的物件。如果省略 ‘thisArg‘,則 ‘undefined‘ 將用作 ‘this‘ 值。 |
返回值
其中的每個元素均為關聯的原始陣列元素的回撥函式返回值的新陣列。
異常
如果 callbackfn
引數不是函式物件,則將引發 TypeError
異常。
備註
對於陣列中的每個元素,map
方法都會呼叫 callbackfn
函式一次(採用升序索引順序)。
不為陣列中缺少的元素呼叫該回調函式。
除了陣列物件之外,map
方法可由具有 length
屬性且具有已按數字編制索引的屬性名的任何物件使用。
回撥函式語法
回撥函式的語法如下所示:
functioncallbackfn(value, index, array1)
可使用最多三個引數來宣告回撥函式。
下表列出了回撥函式引數。
回撥引數 | 定義 |
---|---|
value | 陣列元素的值。 |
index | 陣列元素的數字索引。 |
array1 | 包含該元素的陣列物件。 |
修改陣列物件
陣列物件可由回撥函式修改。
下表描述了在 map
方法啟動後修改陣列物件所獲得的結果。
‘map‘ 方法啟動後的條件 | 元素是否傳遞給回撥函式 |
---|---|
在陣列的原始長度之外新增元素。 | 否。 |
新增元素以填充陣列中缺少的元素。 | 是,如果該索引尚未傳遞給回撥函式。 |
元素被更改。 | 是,如果該元素尚未傳遞給回撥函式。 |
從陣列中刪除元素。 | 否,除非該元素已傳遞給回撥函式。 |
示例
下面的示例闡釋了 map
方法的用法。
// 定義回撥函式
// 計算圓的面積
functionAreaOfCircle(radius){
var area = Math.PI * (radius * radius);
return area.toFixed(0);
}
// 定義一個數組,保護三個元素
var radii = [10, 20, 30];
// 計算 radii 的面積.
var areas = radii.map(AreaOfCircle);
document.write(areas);
// 輸出:
// 314,1257,2827
下面的示例闡釋 thisArg
引數的用法,該引數指定對其引用 this
關鍵字的物件。
// 定義一個物件 object,保護 divisor 屬性和 remainder 方法
// remainder 函式求每個傳入的值的個位數。(即除以 10 取餘數)
var obj = {
divisor: 10,
remainder: function(value){
return value % this.divisor;
}
}
// 定義一個包含 4 個元素的陣列
var numbers = [6, 12, 25, 30];
// 對 numbers 陣列的每個元素呼叫 obj 物件的 remainder 函式。
// map 函式的第 2 個引數傳入 ogj。
var result = numbers.map(obj.remainder, obj);
document.write(result);
// 輸出:
// 6,2,5,0
在下面的示例中,內建 JavaScript 方法用作回撥函式。
// 對陣列中的每個元素呼叫 Math.sqrt(value) (求平方根)
var numbers = [9, 16];
var result = numbers.map(Math.sqrt);
document.write(result);
// 輸出: 3,4
[9,16].map(Math.sqrt)
回撥函式,輸出的結果是 [3,4]
。
但是為什麼 ["1","2","3"].map(parseInt)
卻返回 [1,NaN,NaN]
?
網站給出的提示是:
what you actually get is
[1,NaN,NaN]
becauseparseInt
takes two parameters(val, radix)
andmap
passes 3(element, index, array)
簡單翻譯一下就是
parseInt
需要 2 個引數(val, radix)
, 而map
傳遞了 3 個引數(element, index, array)
」。
通過上面的解釋,我們可以看出,如果想讓 parseInt(string,
radix)
返回 NaN,有兩種情況:
-
第一個引數不能轉換成數字。
-
第二個引數不在 2 到 36 之間。
我們傳入的引數都能轉換成數字,所以只能是第二種可能。
到底是不是呢?我們重新定義 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"]
我們再繼續增加引數:
var parseInt = function(string, radix, obj, other){
return string + "-" + radix + "-" + obj + "-" + other;
};
["1", "2", "3"].map(parseInt);
輸出結果:
["1-0-1,2,3-undefined", "2-1-1,2,3-undefined", "3-2-1,2,3-undefined"]
第四個引數為 undefined
,看見 map
確實為 parseInt
傳遞了三個引數。就像作者寫道的:
(element, index, array)
-
陣列的值
-
陣列的索引
-
陣列
(全文完)