JavaScript Puzzlers! 被稱爲 javascript 界的專業八級測驗,感興趣的 jser 能夠去試試。
我試了一下, 36 道題只作對了 19 道, 算下來正確率爲 53%,尚未及格。javascript
第一題爲 ["1", "2", "3"].map(parseInt)
的返回值。html
> ["1", "2", "3"].map(parseInt) [1, NaN, NaN]
在 javascript 中 ["1", "2", "3"].map(parseInt)
爲什麼返回不是 [1,2,3]
倒是 [1,NaN,NaN]
?java
咱們首先回顧一下 parseInt()
個 map()
兩個函數的用法:數組
parseInt()
函數可解析一個字符串,並返回一個整數。app
parseInt(string, radix)
參數 | 描述 |
---|---|
string | 必需。要被解析的字符串。 |
radix | 可選。表示要解析的數字的基數。該值介於 2 ~ 36 之間。函數 若是省略該參數或其值爲 `0`,則數字將以 10 爲基礎來解析。若是它以 `"0x"` 或 `"0X"` 開頭,將以 16 爲基數。網站 若是該參數小於 2 或者大於 36,則 `parseInt()` 將返回 `NaN`。this |
返回解析後的數字。翻譯
當參數 radix
的值爲 0
,或沒有設置該參數時,parseInt()
會根據 string
來判斷數字的基數。code
舉例:
若是 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
對數組的每一個元素調用定義的回調函數並返回包含結果的數組。
array1.map(callbackfn[, thisArg])
參數 | 定義 |
---|---|
array1 | 必需。一個數組對象。 |
callbackfn | 必需。一個接受**最多**三個參數的函數。對於數組中的每一個元素,`map` 方法都會調用 `callbackfn` 函數一次。 |
thisArg | 可選。可在 `callbackfn` 函數中爲其引用 `this` 關鍵字的對象。若是省略 `thisArg`,則 `undefined` 將用做 `this` 值。 |
其中的每一個元素均爲關聯的原始數組元素的回調函數返回值的新數組。
若是 callbackfn
參數不是函數對象,則將引起 TypeError
異常。
對於數組中的每一個元素,map
方法都會調用 callbackfn
函數一次(採用升序索引順序)。 不爲數組中缺乏的元素調用該回調函數。
除了數組對象以外,map
方法可由具備 length
屬性且具備已按數字編制索引的屬性名的任何對象使用。
回調函數的語法以下所示:
function callbackfn(value, index, array1)
可以使用最多三個參數來聲明回調函數。
下表列出了回調函數參數。
回調參數 | 定義 |
---|---|
value | 數組元素的值。 |
index | 數組元素的數字索引。 |
array1 | 包含該元素的數組對象。 |
數組對象可由回調函數修改。
下表描述了在 map
方法啓動後修改數組對象所得到的結果。
`map` 方法啓動後的條件 | 元素是否傳遞給回調函數 |
---|---|
在數組的原始長度以外添加元素。 | 否。 |
添加元素以填充數組中缺乏的元素。 | 是,若是該索引還沒有傳遞給回調函數。 |
元素被更改。 | 是,若是該元素還沒有傳遞給回調函數。 |
從數組中刪除元素。 | 否,除非該元素已傳遞給回調函數。 |
下面的示例闡釋了 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); 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)
數組的值
數組的索引
數組
UPDATE 原文勘誤:(謝謝 米糉糉 提醒)
["1", "2", "3"].map(parseInt)
應該對應的是:
[parseInt("1", 0), parseInt("2", 1), parseInt("3", 2)]
parseInt("3", 2)
的第二個參數是界於 2-36 之間的,之因此返回 NaN
是由於 字符串 "3"
裏面沒有合法的二進制數,因此 NaN
。
咱們還能夠繼續試驗:
> ["1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"].map(parseInt) [1, NaN, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
只有當第二個參數是 1
的時候返回 NaN
,其它狀況都返回 1
。
> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"].map(parseInt) [1, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 9, 11, 13, 15, 17, 19, 21]
簡單列舉一下:
parseInt("1", 0); // 十進制 1 parseInt("2", 1); // 第二個參數不在 2-36 直接 parseInt("3", 2); // 二進制 NaN parseInt("4", 3); // 三進制 parseInt("5", 4); parseInt("6", 5); parseInt("7", 6); parseInt("8", 7); parseInt("9", 8); parseInt("10", 9); // 九進制 (1*9+0 = 9) parseInt("11", 10); // 十進制 (1*10+1 = 11) parseInt("12", 11); parseInt("13", 12); parseInt("14", 13); parseInt("15", 14); parseInt("16", 15);
(全文完)
文章來自個人我的博客:JavaScript Puzzlers 解密(一):爲何 ["1", "2", "3"].map(parseInt) 返回 [1, NaN, NaN]?