["1", "2", "3"].map(parseInt)?


["1", "2", "3"].map(parseInt)得到什么?

答案是:[1, NaN, NaN].

原因:主要是下面這3點

1. map函數傳遞參數的定義

2. parseInt函數針對於radix這個參數的理解

3. 二進制當中沒有"3"這個數碼

接下來具體看一下是為什么

-------------------------------------------------分割線------------------------------------------------------------------

昨天收到網友的留言,覺得確實之前的思路有一點亂,這里整理一下思路,重新寫一下。希望可以幫助到后面看到這篇文章的同學。

這個問題我們最開始可能以為的答案會是

[1, 2, 3]

為什么會產生這種想法,因為我們通常使用map函數的時候都會傳入一個函數,這個函數一般只使用1-2個參數,如下所示:

var arr = ["1", "2", "3"].map(function(item){
   // 這個地方只傳入一個參數
    return item;
});

console.log(arr);
// ["1", "2", "3"]
var arr = ["1", "2", "3"].map(function(item, index){
   // 這個地方傳入兩個參數
    return "value:" + item + ", index:" + index;
});
console.log(arr);
// ["value:1, index:0", "value:2, index:1", "value:3, index:2"]

可以看到,其實得到的結果取決於傳進去的參數,還有function函數的執行過程。

標准定義下,map方法會傳遞3個參數

arr.map(function(item, index, arr){
      .....     
});

這個時候,題目中的問題就轉化為下面的函數求解

 

var arr = ["1","2","3"];
arr.map((value,index,array) => parseInt(value,index));
//parseInt(string,radix)

 

這個前提是,我們需要知道parseInt函數本身是怎么定義的?

接下來看一下parseInt的官方定義

parseInt(stringradix);

string: 需要轉化的字符,如果不是字符串會被轉換,忽視空格符。

radix:數字2-36之前的整型。默認使用10,表示十進制。這個參數的意義是指把前面的字符看作是多少進制的數字,所謂的基數

如下所示:

 // 將'123'看作5進制數,返回十進制數38 => 1*5^2 + 2*5^1 + 3*5^0 = 38
parseInt('123', 5)

需要注意的是,如果radix在2-36之外會返回NaN

在沒有指定基數,或者基數為 0 的情況下,JavaScript 作如下處理:

  • 如果字符串 string 以"0x"或者"0X"開頭, 則基數是16 (16進制).
  • 如果字符串 string 以"0"開頭, 基數是8(八進制)或者10(十進制),那么具體是哪個基數由實現環境決定。ECMAScript 5 規定使用10,但是並不是所有的瀏覽器都遵循這個規定。因此,永遠都要明確給出radix參數的值
  • 如果字符串 string 以其它任何值開頭,則基數是10 (十進制)。

因為parseInt只接收2個參數,因此map的callback函數就只傳遞(item, index)這兩個值給parseInt。

那么上面的函數就可以分解為求解下面這三個函數的值,並返回結果

parseInt('1', 0); // 1 (parseInt的處理方式,這個地方item沒有以"0x"或者"0X"開始,8和10這個基數由實現環境來定,ES5規定使用10來作為基數,因此這個0相當於傳遞了10)
parseInt('2', 1); // NaN (因為parseInt的定義,超出了radix的界限)
parseInt('3', 2); // NaN (雖然沒有超出界限,但是二進制里面沒有3,因此返回NaN)

 

再重復總結一下這道題的三個考點:

1. map函數傳遞參數的定義,此處本身map函數是有3個參數可以傳遞的

2. parseInt函數針對於radix這個參數的理解,針對於0,2-36以外界限的定義

3. 二進制當中沒有"3"這個數碼

我想結合我上面的分析,再加上我下面的一些知識補充,應該可以對這個問題有一個很清晰的認識了吧~

------------------------------------------------------------------------------------------------------------------------

map函數定義

arr.map(callback[,thisArg]);

callback

原數組中的元素經過該方法后返回一個新的元素。

currentValue 
     callback的第一個參數,數組中當前被傳遞的元素。
index
     callback的第二個參數,數組中當前被傳遞的元素的索引。
array
     callback的第三個參數,調用 map 方法的數組。

thisArg可選.  callback函數里的this值 默認是window對象

下面我們將parseInt重新定義,看一下會返回什么?

執行下面的函數:

var parseInt = function (string, radix, others) {
    return string + '-' + radix + '-' + others;
};
['1','2','3'].map(parseInt);

得到:image

為什么會得到這個數組:以數組第一個字符串為例,1-0-1,2,3是因為map的callback返回參數分別是currentValue:1,index:0,array:[1,2,3](此處被轉義)。

其他同上。那么接下來,我們將map函數執行原始parseInt函數拆分執行:

parseInt函數定義:

parseInt(stringradix);

string: 需要轉化的字符,如果不是字符串會被轉換,忽視空格符。

radix:數字2-36之前的整型。默認使用10,表示十進制。

需要注意的是,如果radix在2-36之外會返回NaN。

因為parseInt函數接收2個參數,string,radix,如果map函數返回了這兩個參數,不管意義是否是所期望的,都會將其作為參數執行。

以1-0-1,2,3為例,map(parseInt)中,parseInt作為callback函數執行的將是:parseInt('1',0)(前面那個數字1自動被轉換為字符串1),其他同上。

看下面的執行函數結果

parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);

所以得到1,NaN,NaN

因此,在最開始的題目["1", "2", "3"].map(parseInt)得到的是1,NaN,NaN。

(此處如果出錯,主要是對map的callback返回參數和parseInt會接受2個參數的不熟悉)

 

Map函數的其他用途:

例1:遍歷querySelectorAll對象,並執行相關函數

var elems = document.querySelectorAll('div');
var values = Array.prototype.map.call(elems, function (elem) {
    return elem;
});

例2:反轉字符串

var str = '12345';
Array.prototype.map.call(str, function(x){
    return x;
}).reverse().join();

還有一種翻轉字符的方法:

var str = '12345';

var strre = str.split('').reverse().join('');

附:這個方法可以判斷回文

var str = '12345';
var str1 = Array.prototype.map.call(str, function(x){
    return x;
}).reverse().join();

if (str === str1) {
   console.log('true');
} else {
   console.log('false');
}


免責聲明!

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



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