翻譯 alentan
Javascript很奇怪锻梳。不相信我?嘗試使用map和parseInt將字符串?dāng)?shù)組轉(zhuǎn)換為整數(shù)挺举。啟動(dòng)控制臺(tái)(Chrome上的F12)创橄,粘貼以下內(nèi)容命斧,然后按Enter
['1', '7', '11'].map(parseInt);
復(fù)制代碼
我們最終得到的不是一個(gè)[1, 7, 11] 這樣的整數(shù)數(shù)組,而是這樣的長(zhǎng)這樣的 [1, NaN, 3] 一個(gè)數(shù)組。要了解到底發(fā)生了什么竭业,我們首先要討論一些 Javascript 概念智润。如果你想要一個(gè)摘要(TLDR),我在本故事結(jié)尾處加入了一個(gè)快速摘要未辆。
真值 & 假值
這是Javascript中一個(gè)簡(jiǎn)單的if-else語(yǔ)句:
if (true) {
// 永遠(yuǎn)都會(huì)運(yùn)行
} else {
// 永遠(yuǎn)不會(huì)運(yùn)行
}
復(fù)制代碼
在這種情況下窟绷,if-else 語(yǔ)句的條件為 true,因此始終執(zhí)行 if-block 語(yǔ)句塊并忽略 else-block 語(yǔ)句塊咐柜。這是一個(gè)簡(jiǎn)單的例子兼蜈,因?yàn)?true 是一個(gè)布爾值攘残。如果我們將非布爾值作為條件會(huì)怎么樣呢?
if ("hello world") {
// 他會(huì)運(yùn)行嗎?
console.log("Condition is truthy");
} else {
// 還是運(yùn)行這個(gè)?
console.log("Condition is falsy");
}
復(fù)制代碼
嘗試在瀏覽器的控制臺(tái)中運(yùn)行此代碼(Chrome上的F12)为狸。您應(yīng)該發(fā)現(xiàn) if-block 語(yǔ)句塊運(yùn)行歼郭。這是因?yàn)樽址畬?duì)象"hello world"是true。
每個(gè)Javascript對(duì)象當(dāng)放置在布爾上下文中時(shí)都是真值或假值辐棒。例如 if-else 語(yǔ)句病曾,會(huì)把Javascript對(duì)象轉(zhuǎn)為true或false。那么哪些對(duì)象是true的漾根,哪些是false的呢泰涂?這是一個(gè)簡(jiǎn)單的規(guī)則:
Javascript中當(dāng)以下的值放置在布爾上下文中時(shí)會(huì)返回false
false,0(""空字符串)辐怕,null负敏,undefined和NaN。
進(jìn)制(基數(shù))
0 1 2 3 4 5 6 7 8 9 10
復(fù)制代碼
當(dāng)我們從0到9計(jì)數(shù)時(shí)秘蛇,每個(gè)數(shù)字(0-9)都有不同的符號(hào)其做。但是,一旦我們達(dá)到10赁还,我們需要兩個(gè)不同的符號(hào)(1和0)來(lái)表示數(shù)字妖泄。這是因?yàn)槲覀兊男?shù)計(jì)數(shù)系統(tǒng)的基數(shù)(或進(jìn)制)為10。
基數(shù)是最小的數(shù)字艘策,只能由多個(gè)符號(hào)表示蹈胡。不同的計(jì)數(shù)系統(tǒng)具有不同的基數(shù),因此朋蔫,相同的數(shù)字可以指計(jì)數(shù)系統(tǒng)中的不同數(shù)字罚渐。
10進(jìn)制 二進(jìn)制 16進(jìn)制
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
復(fù)制代碼
例如,查看上表驯妄,我們看到相同的數(shù)字11可以表示不同計(jì)數(shù)系統(tǒng)中的不同數(shù)字荷并。如果進(jìn)制(基數(shù))為2,則表示數(shù)字 3青扔。如果進(jìn)制(基數(shù))為16源织,則表示數(shù)字17。
您可能已經(jīng)注意到微猖,在我們的示例中谈息,當(dāng)輸入為11時(shí),parseInt返回3凛剥,這對(duì)應(yīng)于上表中的二進(jìn)制列侠仇。
函數(shù)參數(shù)
Javascript中的函數(shù)可以使用任意數(shù)量的參數(shù)調(diào)用,即使它們不等于聲明的函數(shù)參數(shù)的數(shù)量犁珠。缺少的參數(shù)被視為未定義逻炊,而多余的參數(shù)會(huì)被忽略(但會(huì)存儲(chǔ)在類(lèi)似數(shù)組的參數(shù)對(duì)象中)互亮。
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
復(fù)制代碼
map()函數(shù)
我們快到了!
Map是Array原型中的一個(gè)方法嗅骄,它返回一個(gè)新的數(shù)組胳挎,其結(jié)果是將原始數(shù)組的每個(gè)元素傳遞給一個(gè)函數(shù)。例如溺森,以下代碼將數(shù)組中的每個(gè)元素乘以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];
復(fù)制代碼
現(xiàn)在慕爬,假設(shè)我想使用map()(沒(méi)有返回語(yǔ)句)記錄每個(gè)元素。我應(yīng)該能夠console.log作為一個(gè)參數(shù)傳遞給map()......
[1,2,3,4,5] .map(console.log);
復(fù)制代碼
[圖片上傳失敗...(image-4ee30b-1562899087851)]
<figcaption></figcaption>
一些非常奇怪的事情正在發(fā)生屏积。每次console.log調(diào)用都記錄索引和完整數(shù)組医窿,而不是僅記錄值。
[1, 2, 3, 4, 5].map(console.log);
// 上面的例子相當(dāng)于
[1, 2, 3, 4, 5].map(
(val, index, array) => console.log(val, index, array)
);
// 而不是這樣
[1, 2, 3, 4, 5].map(
val => console.log(val)
);
復(fù)制代碼
當(dāng)一個(gè)函數(shù)傳遞到map()炊林,對(duì)于每次迭代姥卢,三個(gè)參數(shù)傳遞到函數(shù):currentValue,currentIndex渣聚,和完整的array独榴。這就是每次迭代記錄三個(gè)條目的原因。
我們現(xiàn)在擁有解決這個(gè)謎團(tuán)所需的所有部分奕枝。
解開(kāi)謎團(tuán)
ParseInt有兩個(gè)參數(shù):string和radix(進(jìn)制)棺榔。如果提供的radix(進(jìn)制)為空或者為假值,進(jìn)制(基數(shù))默認(rèn)設(shè)置為10隘道。
parseInt('11'); => 11
parseInt('11', 2); => 3
parseInt('11', 16); => 17
parseInt('11', undefined); => 11 (radix(進(jìn)制) 為假)
parseInt('11', 0); => 11 (radix(進(jìn)制) 為假)
復(fù)制代碼
現(xiàn)在讓我們一步一步地運(yùn)行我們的示例症歇。
['1', '7', '11'].map(parseInt); => [1, NaN, 3]
// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1
復(fù)制代碼
由于0是假的,因此進(jìn)制(基數(shù))設(shè)置為默認(rèn)值10谭梗。 parseInt()只接受兩個(gè)參數(shù)忘晤,因此['1', '7', '11']會(huì)被 忽略。字符串'1'在10進(jìn)制(基數(shù))中的字符串表示數(shù)字1激捏。
// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN
復(fù)制代碼
在進(jìn)制(基數(shù))為1系統(tǒng)中设塔,符號(hào)'7'不存在。與第一次迭代一樣缩幸,忽略最后一個(gè)參數(shù)壹置。所以,parseInt()返回了NaN表谊。
// 第三次迭代: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3
復(fù)制代碼
在進(jìn)制(基數(shù))為2(二進(jìn)制)系統(tǒng)中,符號(hào)'11'表示數(shù)字3盖喷,最后一個(gè)參數(shù)被忽略爆办。
摘要(TLDR)
['1', '7', '11'].map(parseInt) 不能按預(yù)期工作,因?yàn)樵诿看蔚?map 傳遞三個(gè)參數(shù)到 parseInt()课梳。第二個(gè)參數(shù) index 作為radix(進(jìn)制)參數(shù)傳遞給 parseInt 距辆。因此余佃,使用不同的進(jìn)制(基數(shù))解析數(shù)組中的每個(gè)字符串。'7' 被解析為進(jìn)制(基數(shù))為 1跨算,它是 NaN爆土,'11' 被解析為進(jìn)制(基數(shù))為 2,它的值為 3诸蚕,'1' 被解析為默認(rèn)的進(jìn)制(基數(shù))為 10步势,因?yàn)樗乃饕?0 是假值。
作者:alentan
鏈接:https://juejin.im/post/5d0202da51882546dd10087b
來(lái)源:掘金
著作權(quán)歸作者所有背犯。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)坏瘩,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。