JS 中爲啥 ['1', '7', '11'].map(parseInt) 返回 [1, NaN, 3]

阿里雲最近在作活動,低至2折,有興趣能夠看看:
https://promotion.aliyun.com/...

爲了保證的可讀性,本文采用意譯而非直譯。html

Javascript 一直是神奇的語言。 不相信我? 嘗試使用mapparseInt將字符串數組轉換爲整數。打開 Chrome 的控制檯(F12),粘貼如下內容,而後按回車,查看輸出結果:前端

['1', '7', '11'].map(parseInt);git

咱們獲得的不是一個整數數組[1,7,11],而是[1,NAN, 3],要了解究竟發生了什麼,咱們首先要討論一些Javascript概念。github

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!數組

真值(truthy) & 虛值(falsy)

如下是 JS 中一個簡單的if-else語句:函數

if (true) {
    // this always runs
} else {
    // this never runs
}

在上例中,if 條件爲 true,所以老是執行if塊,忽略else塊。這是一個簡單的例子,由於true是一個布爾值。若是咱們把非布爾值做爲條件呢 ?工具

if ("hello world") {
    console.log("Condition is truthy");
} else {
    console.log("Condition is falsy");
}

打開控制檯並運行上述代碼,會打印 Condition is truthy,說明條件 "hello world"真(true)值。學習

在 JavaScript 中,Truthy (真值)指的是在 布爾值 上下文中轉換後的值爲真的值。全部值都是真值,除非它們被定義爲 falsy (即除了 false0""nullundefinedNaN 外)。this

falsy(虛值)是在 Boolean 上下文中已認定可轉換爲‘假‘的值。阿里雲

JS中的對象不是真值就是虛值。

使人困惑的是,這意味着字符串「false」,字符串「0」,空對象{}和空數組[]都是真的。 使用使用 Boolean 方法來驗證,如 Boolean("0")

出於咱們的目的,接下來只要記住0是假的就好了。

基數

在數學上,基數(cardinal number)是集合論中刻畫任意集合大小的一個概念。兩個可以創建元素間一一對應的集合稱爲互相對等集合。例如3我的的集合和3匹馬的集合能夠創建一一對應,是兩個對等的集合。

0 1 2 3 4 5 6 7 8 9 10

當咱們從0數到9時,每一個數字(0-9)都有不一樣的符號,可是當咱們數到10時,咱們須要兩個不一樣的符號(10)來表示這個數字。這是由於咱們的十進制計數系統的基數是10

基數是最小的數字,只能由多個符號表示。 不一樣的計數系統具備不一樣的基數,所以,相同的數字在不一樣的計數系統中能夠表示不一樣的數字。

十進制   二進制    十六進制
RADIX=10  RADIX=2   RADIX=16
0         0         0
1         1         1
2         10        2
3         11        3
4         100       4
5         101       5
6         110       6
7         111       7
8         1000      8
9         1001      9
10        1010      A
11        1011      B
12        1100      C
13        1101      D
14        1110      E
15        1111      F
16        10000     10
17        10001     11

看上表,能夠看到相同的數字11在不一樣的計數系統中能夠表示不一樣的數字。若是基數是2,那麼它表示數字爲 3。若是基數是16,那麼它指的是數字17

你可能已經注意到,在咱們的示例中,當輸入爲11時,parseInt返回3,這對應於上表中的二進制列。

函數參數

JS 中函數調用,咱們能夠傳入任意的參數,即便它們不等於聲明時的函數參數的數量。缺乏的參數被視爲undefined 的,而且會忽略額外的參數,但會保存在相似數組的arguments對象中。

function foo(x, y) {
    console.log(x);
    console.log(y);
}
foo(1, 2);      // 打印 1, 2
foo(1);         // 打印 1, undefined
foo(1, 2, 3);   // 打印 1, 2

map()

map是 Es6 中新出的一個數組方法,它是一個高階函數,經過傳入一個函數進行邏輯操做,並返回一個數組, 例如,如下代碼將數組中的每一個元素乘以3

function multiplyBy3(x) {
    return x * 3;
}
const result = [1, 2, 3, 4, 5].map(multiplyBy3);
console.log(result);   // logs [3, 6, 9, 12, 15];

如今,將console.log做爲參數傳給 map,來打印數組的元素:

[1, 2, 3, 4, 5].map(console.log);

等價於
 
 [1, 2, 3, 4, 5].map((val, index, array) => 
     console.log(val, index, array));

clipboard.png

因此 map 回調方法中會傳入三個參數,分別是 當前遍歷的項,當前索引,及遍歷的整個數組。

緣由

ParseInt有兩個參數:stringradix。 若是提供的基數是虛值,則默認狀況下,基數設置爲10

parseInt('11');                => 11
parseInt('11', 2);             => 3
parseInt('11', 16);            => 17
parseInt('11', undefined);     => 11 (radix is falsy)
parseInt('11', 0);             => 11 (radix is falsy)

如今一步一步解析開頭的事例。

['1', '7', '11'].map(parseInt);       => [1, NaN, 3]

// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']);   => 1

由於0是虛值,基數設置爲默認值10parseInt()只接受兩個參數,所以忽略了第三個參數['1'、'7'、'11']。以10爲基數的字符串「1」表示數字1

// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']);   => NaN

在基數1系統中,符號「7」不存在。與第一次迭代同樣,忽略最後一個參數。所以,parseInt()返回NaN

// Third iteration: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']);   => 3

在基數2(二進制)系統中,符號「11」表示數字3

至此緣由已經明瞭了。 有興趣能夠試着寫下下列的打印結果:

['1', '7', '11'].map(numStr => parseInt(numStr));

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

## 交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索