四個(gè)編寫JavaScript代碼的關(guān)鍵原則
1、以強(qiáng)類型語言的風(fēng)格編寫代碼
JavaScript 是一種弱類型編程語言,其中變量在語法上可以具有不同類型的值。但是為了提高編譯性能并使您的代碼更容易被其他程序員閱讀,建議您以強(qiáng)類型風(fēng)格編寫代碼。
1)、定義變量時(shí)應(yīng)指定數(shù)據(jù)類型
錯(cuò)誤代碼:
上述代碼中的變量缺少類型信息,導(dǎo)致其他程序員難以理解代碼或 JavaScript 解釋器無法優(yōu)化。
好代碼:
2)、不要隨意改變變量的類型
錯(cuò)誤代碼:
earning開始是一個(gè)整數(shù),然后變成一個(gè)字符串。如果其他人需要閱讀或修改這段代碼,他或她必然會(huì)對(duì)代碼產(chǎn)生懷疑,甚至?xí)懗鲥e(cuò)誤的代碼。
同時(shí),像 V8 這樣的引擎中的 JavaScript 代碼被轉(zhuǎn)換為字節(jié)碼然后執(zhí)行,字節(jié)碼中的數(shù)據(jù)類型是確定的。如果我們?cè)?JavaScript 代碼中更改變量的數(shù)據(jù)類型,編譯器必須做一些額外的處理,這會(huì)降低程序的性能。
好代碼:
當(dāng)你需要轉(zhuǎn)換一個(gè)值的類型時(shí),使用一個(gè)新的變量。
3)、函數(shù)的返回類型應(yīng)該是固定的
錯(cuò)誤代碼:
此函數(shù)可能返回整數(shù)或字符串。盡管這符合 JavaScript 語法,但調(diào)用函數(shù)的人很難直接使用 getPrice() 的結(jié)果進(jìn)行算術(shù)運(yùn)算。
好代碼:
我們可以在函數(shù)注釋中同意返回 -1 表示參數(shù)無效,這允許調(diào)用者以統(tǒng)一的方式處理函數(shù)的結(jié)果。
2、減少不必要的范圍查找
JavaScript 支持嵌套作用域和作用域鏈,這使我們能夠編寫高效的代碼。但是錯(cuò)誤地使用這些語法會(huì)弄亂代碼。
1)、如果沒有必要,不要將你的代碼暴露在全局范圍內(nèi)
錯(cuò)誤代碼:
首先,script標(biāo)簽中的所有變量都在全局范圍內(nèi),不同的script標(biāo)簽中的代碼可能是由不同的程序員開發(fā)的,可能會(huì)造成命名沖突。
其次,上面第二行代碼,在使用元素變量的時(shí)候,在全局范圍內(nèi)尋找元素變量,降低了程序的性能。
好代碼:
這樣,我們使用閉包來隱藏元素變量,這樣不會(huì)污染全局作用域,在局部作用域中查找變量也更快。
當(dāng)然,如果您確定將在其他地方使用元素變量,您仍然應(yīng)該在全局范圍內(nèi)公開它。
2)、不要濫用閉包
JavaScript 通過作用域鏈查找變量,如果在當(dāng)前作用域中找不到變量,JavaScript 引擎會(huì)在當(dāng)前作用域的父作用域中查找,然后逐級(jí)查找全局作用域。所以閉包嵌套得越深,變量查找所需的時(shí)間就越長(zhǎng)。
錯(cuò)誤代碼:
在 process 函數(shù)內(nèi)部使用了上一級(jí)作用域變量 count,這使得 JavaScript 引擎在調(diào)用 process 函數(shù)時(shí)查找 count 變量更加耗時(shí)。
同時(shí),如果作用域嵌套多層,process和count之間有幾十行代碼,在讀取process函數(shù)時(shí)很容易混淆count變量。
更好的方法是將計(jì)數(shù)作為參數(shù)傳遞給處理。
好代碼:
3、使用ES6特性簡(jiǎn)化代碼
ES6 已經(jīng)存在多年,現(xiàn)在非常兼容,我們應(yīng)該積極擁抱 ES6,讓代碼更加簡(jiǎn)潔優(yōu)雅。
1)、使用箭頭函數(shù)代替普通函數(shù)作為回調(diào)函數(shù)
如果您不需要考慮此綁定,最好使用箭頭函數(shù)而不是普通函數(shù)作為回調(diào)。
錯(cuò)誤代碼:
好代碼:
2)、使用類
使用傳統(tǒng)的原型語法會(huì)將構(gòu)造函數(shù)代碼與原型方法代碼分離,無法有效組織代碼。
錯(cuò)誤代碼:
使用類使代碼更簡(jiǎn)單、更容易理解,而使用類還可以輕松實(shí)現(xiàn)繼承的靜態(tài)成員函數(shù)。
好代碼:
3)、使用模板字符串
模板字符串用反引號(hào) () 字符而不是雙引號(hào)或單引號(hào)括起來。
錯(cuò)誤代碼:
在模板字符串中,我們可以使用任何字符而不是轉(zhuǎn)義字符,如 \n。
同時(shí),我們可以直接使用表達(dá)式 ${} 來插入變量,而不是拆分字符串并使用 + 來連接。
好代碼:
這顯然更容易閱讀。
4)、使用默認(rèn)參數(shù)
在 ES5 中,如果我們想給函數(shù)的參數(shù)一個(gè)默認(rèn)值,我們可以這樣寫:
在 ES6 中,我們可以用一種更簡(jiǎn)單、更易讀的方式編寫:
5)、使用塊范圍變量
如果我們希望控制臺(tái)以 100 毫秒的間隔打印出 0、1、2、…10,反過來,有些人可能會(huì)編寫如下代碼:
for(var index = 0; index <= 10; index++){
setTimeout(() => console.log(index), 100)
}
不幸的是,上面的代碼不能滿足要求。因?yàn)?var 聲明的變量是在全局范圍內(nèi),所以當(dāng) setTimeout 回調(diào)函數(shù)執(zhí)行時(shí),index 的值已經(jīng)變成了 11。
ES5 中的一種解決方案是使用閉包:
for(var index = 0; index <= 10; index++){
(function(archivedIndex){
setTimeout(() => console.log(archivedIndex), 100)
})(index)
}
這里我們通過閉包保存索引值,這樣每次執(zhí)行setTimeout都會(huì)找到正確的索引值。
但是上面的寫法很麻煩,很難看懂,更好的方法是使用 let 聲明塊范圍的變量。
for(let index = 0; index <= 10; index++){
setTimeout(() => console.log(index), 100)
}
只需更改三個(gè)字符即可完成要求,非常簡(jiǎn)單、方便、易讀。
4、語法風(fēng)格
1)、用三元運(yùn)算符替換簡(jiǎn)單的 if-else
一般來說,三元運(yùn)算符的語法如下:
condition ? expression_1 : expression_2;
條件是一個(gè)表達(dá)式,計(jì)算結(jié)果為布爾值,真或假。如果條件為真,則三元運(yùn)算符返回表達(dá)式_1,否則返回表達(dá)式_2。
錯(cuò)誤代碼:
好的代碼:
2)、避免==
== 有很多特殊的機(jī)制,過多地使用 == 會(huì)使我們的代碼更難理解。我們可以顯式轉(zhuǎn)換數(shù)據(jù)類型以使代碼更易于理解。
錯(cuò)誤代碼:
好的代碼: