JavaScript之map與parseInt的陷阱


問題來源

​ 這個問題的來源是學習廖雪峰老師JS教程。問題如下:小明希望利用map()把字符串變成整數,他寫的代碼很簡潔:

'use strict';

var arr = ['1', '2', '3'];
var r;
r = arr.map(parseInt);
console.log(r);
// [1, NaN, NaN]

為什么不是[1, 2, 3]?這是因為兩個兩個函數的定義有沖突。下面詳解:

map的定義

​ 注意到這個問題的原因是參考了這個國外某博客JavaScript可選參數危險。首先,我們了解一下map方法的定義,如下:

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
    // Return element for new_array
}[, thisArg])

其中參數有一個函數callback,這個函數需要三個參數:currentValue(必須):處理的數組中的當前元素;index(可選):當前處理的元素在數組中的索引值;array(可選):調用map的數組。thisArg(可選):對象作為該執行回調時使用,傳遞給函數,用作 "this" 的值。
如果省略了 thisValue ,"this" 的值為 "undefined"。

​ 所以,map函數接收的是兩個參數,一個函數,另一個是thisArg。這里我們主要關注的是其中的函數接收三個參數,一個必須,兩個可選。問題就是出現在這里,函數接收三個參數。

parseInt的定義

​ 這個函數用於解析一個字符串,並返回一個整數。定義如下:

parseInt(string, radix)

參數string(必須):表示的是要被解析的字符串。radix(可選):表示表示要解析的數字的基數。該值介於 2 ~ 36 之間。如果省略該參數或其值為 0,則數字將以 10 為基礎來解析。如果它以 “0x” 或 “0X” 開頭,將以 16 為基數。如果該參數小於 2 或者大於 36,則 parseInt() 將返回 NaN。第二個可選參數,就是問題的另一來源了。

問題詳解

​ 了解完兩個函數的定義后,我們就知道小明代碼的問題了:

var arr = ['1', '2', '3'];
var r;
r = arr.map(parseInt);

我們通常以為上述代碼中 arr.map(parseInt);表示的是

parseInt("1")
parseInt("2")
parseInt("3")

實際上應該是:

parseInt("1", 0, arr)
parseInt("2", 1, arr)
parseInt("3", 2, arr)

其中的arr['1', '2', '3']。我們知道,JavaScript函數通常會忽略額外的參數,並且parseInt只需要兩個參數,因此我們不必擔心theArray這些調用中參數的影響。但是,第二個參數對parseInt影響很大。parseInt("1", 0)沒有問題,0表示的是以二進制為基數解析‘1’。但是后面的parseInt("2", 1)以及parseInt("3", 2)就有問題了。1parseInt中是無效的基數,返回‘NaN’值;2雖然是有意義的基數,但是因為‘3’不是合法的二進制數,所以也返回的是NaN。至此,問題錯誤已經明了。下面是解決方案。

解決方案

​ 解決的方法很簡單,就是修飾一些parseInt函數。代碼如下:

'use strict';

var arr = ['1', '2', '3'];
var r;
r = arr.map(function parseInt2(x) {
    return parseInt(x);
});
console.log(r);

或者我們使用Number()方法,這樣也會把字符串參數解析成十進制數,並且只需要一個參數。代碼如下:

'use strict';

var arr = ['1', '2', '3'];
var r;
r = arr.map(Number);
console.log(r);

當然,也可以從map下手解決問題。一個可能的方法如下:

Function.prototype.only = function(numberOfArgs) {
   var self = this; 	//the original function
   return function() {
      return self.apply(this,[].slice.call(arguments,0,numberOfArgs))
   }
};
arr.map(parseInt.only(1));

以上,就是JavaScript中map與parseInt沖突的問題的來源、解析、解決了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM