Javascript很奇怪。不相信我?嘗試使用map和parseInt將字符串數組轉換爲整數。啓動控制檯(Chrome上的F12),粘貼如下內容,而後按Enter翻譯 alentan數組
原文 medium.com/dailyjs瀏覽器
['1', '7', '11'].map(parseInt);
複製代碼
咱們最終獲得的不是一個[1, 7, 11] 這樣的整數數組,而是這樣的長這樣的 [1, NaN, 3] 一個數組。要了解到底發生了什麼,咱們首先要討論一些 Javascript 概念。若是你想要一個摘要(TLDR),我在本故事結尾處加入了一個快速摘要。bash
這是Javascript中一個簡單的if-else語句:函數
if (true) {
// 永遠都會運行
} else {
// 永遠不會運行
}
複製代碼
在這種狀況下,if-else 語句的條件爲 true,所以始終執行 if-block 語句塊並忽略 else-block 語句塊。這是一個簡單的例子,由於 true 是一個布爾值。若是咱們將非布爾值做爲條件會怎麼樣呢?ui
if ("hello world") {
// 他會運行嗎?
console.log("Condition is truthy");
} else {
// 仍是運行這個?
console.log("Condition is falsy");
}
複製代碼
嘗試在瀏覽器的控制檯中運行此代碼(Chrome上的F12)。您應該發現 if-block 語句塊運行。這是由於字符串對象"hello world"是true。spa
每一個Javascript對象當放置在布爾上下文中時都是真值或假值。例如 if-else 語句,會把Javascript對象轉爲true或false。那麼哪些對象是true的,哪些是false的呢?這是一個簡單的規則:翻譯
Javascript中當如下的值放置在布爾上下文中時會返回falsecode
false,0(""空字符串),null,undefined和NaN。cdn
0 1 2 3 4 5 6 7 8 9 10
複製代碼
當咱們從0到9計數時,每一個數字(0-9)都有不一樣的符號。可是,一旦咱們達到10,咱們須要兩個不一樣的符號(1和0)來表示數字。這是由於咱們的小數計數系統的基數(或進制)爲10。對象
基數是最小的數字,只能由多個符號表示。不一樣的計數系統具備不一樣的基數,所以,相同的數字能夠指計數系統中的不一樣數字。
10進制 二進制 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,這對應於上表中的二進制列。
Javascript中的函數可使用任意數量的參數調用,即便它們不等於聲明的函數參數的數量。缺乏的參數被視爲未定義,而多餘的參數會被忽略(但會存儲在相似數組的參數對象中)。
function foo(x, y) {
console.log(x);
console.log(y);
}
foo(1, 2); // logs 1, 2
foo(1); // logs 1, undefined
foo(1, 2, 3); // logs 1, 2
複製代碼
咱們快到了!
Map是Array原型中的一個方法,它返回一個新的數組,其結果是將原始數組的每一個元素傳遞給一個函數。例如,如下代碼將數組中的每一個元素乘以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];
複製代碼
如今,假設我想使用map()(沒有返回語句)記錄每一個元素。我應該可以console.log做爲一個參數傳遞給map()......
[1,2,3,4,5] .map(console.log);
複製代碼
一些很是奇怪的事情正在發生。每次console.log調用都記錄索引和完整數組,而不是僅記錄值。
[1, 2, 3, 4, 5].map(console.log);
// 上面的例子至關於
[1, 2, 3, 4, 5].map(
(val, index, array) => console.log(val, index, array)
);
// 而不是這樣
[1, 2, 3, 4, 5].map(
val => console.log(val)
);
複製代碼
當一個函數傳遞到map(),對於每次迭代,三個參數傳遞到函數:currentValue,currentIndex,和完整的array。這就是每次迭代記錄三個條目的緣由。
咱們如今擁有解決這個謎團所需的全部部分。
ParseInt有兩個參數:string和radix(進制)。若是提供的radix(進制)爲空或者爲假值,進制(基數)默認設置爲10。
parseInt('11'); => 11
parseInt('11', 2); => 3
parseInt('11', 16); => 17
parseInt('11', undefined); => 11 (radix(進制) 爲假)
parseInt('11', 0); => 11 (radix(進制) 爲假)
複製代碼
如今讓咱們一步一步地運行咱們的示例。
['1', '7', '11'].map(parseInt); => [1, NaN, 3]
// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1
複製代碼
因爲0是假的,所以進制(基數)設置爲默認值10。 parseInt()只接受兩個參數,所以['1', '7', '11']會被 忽略。字符串'1'在10進制(基數)中的字符串表示數字1。
// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN
複製代碼
在進制(基數)爲1系統中,符號'7'不存在。與第一次迭代同樣,忽略最後一個參數。因此,parseInt()返回了NaN。
// 第三次迭代: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3
複製代碼
在進制(基數)爲2(二進制)系統中,符號'11'表示數字3,最後一個參數被忽略。
['1', '7', '11'].map(parseInt) 不能按預期工做,由於在每次迭代中 map 傳遞三個參數到 parseInt()。第二個參數 index 做爲radix(進制)參數傳遞給 parseInt 。所以,使用不一樣的進制(基數)解析數組中的每一個字符串。'7' 被解析爲進制(基數)爲 1,它是 NaN,'11' 被解析爲進制(基數)爲 2,它的值爲 3,'1' 被解析爲默認的進制(基數)爲 10,由於它的索引 0 是假值。
不知道你們想明白了沒有