W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
我們的代碼必須盡可能的清晰和易讀。
這實(shí)際上是一種編程藝術(shù) —— 以一種正確并且人們易讀的方式編碼來完成一個(gè)復(fù)雜的任務(wù)。一個(gè)良好的代碼風(fēng)格大大有助于實(shí)現(xiàn)這一點(diǎn)。
下面是一個(gè)備忘單,其中列出了一些建議的規(guī)則(詳情請(qǐng)參閱下文):
現(xiàn)在,讓我們?cè)敿?xì)討論一下這些規(guī)則和它們的原因吧。
沒有什么規(guī)則是“必須”的
沒有什么規(guī)則是“刻在石頭上”的。這些是風(fēng)格偏好,而不是宗教教條。
在大多數(shù)的 JavaScript 項(xiàng)目中,花括號(hào)以 “Egyptian” 風(fēng)格(譯注:“egyptian” 風(fēng)格又稱 K&R 風(fēng)格 —— 代碼段的開括號(hào)位于一行的末尾,而不是另起一行的風(fēng)格)書寫,左花括號(hào)與相應(yīng)的關(guān)鍵詞在同一行上 —— 而不是新起一行。左括號(hào)前還應(yīng)該有一個(gè)空格,如下所示:
if (condition) {
// do this
// ...and that
// ...and that
}
單行構(gòu)造(如 if (condition) doSomething()
)也是一個(gè)重要的用例。我們是否應(yīng)該使用花括號(hào)?如果是,那么在哪里?
下面是這幾種情況的注釋,你可以自己判斷一下它們的可讀性:
if (n < 0) {alert(`Power ${n} is not supported`);}
if (n < 0)
alert(`Power ${n} is not supported`);
if (n < 0) alert(`Power ${n} is not supported`);
if (n < 0) {
alert(`Power ${n} is not supported`);
}
對(duì)于很短的代碼,寫成一行是可以接受的:例如 if (cond) return null
。但是代碼塊(最后一個(gè)示例)通常更具可讀性。
沒有人喜歡讀一長(zhǎng)串代碼,最好將代碼分割一下。
例如:
// 回勾引號(hào) ` 允許將字符串拆分為多行
let str = `
ECMA International's TC39 is a group of JavaScript developers,
implementers, academics, and more, collaborating with the community
to maintain and evolve the definition of JavaScript.
`;
對(duì)于 if
語句:
if (
id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra'
) {
letTheSorceryBegin();
}
一行代碼的最大長(zhǎng)度應(yīng)該在團(tuán)隊(duì)層面上達(dá)成一致。通常是 80 或 120 個(gè)字符。
有兩種類型的縮進(jìn):
一個(gè)水平縮進(jìn)通常由 2 或 4 個(gè)空格或者 “Tab” 制表符(?Tab
?鍵)構(gòu)成。選擇哪一個(gè)方式是一場(chǎng)古老的圣戰(zhàn)。如今空格更普遍一點(diǎn)。
選擇空格而不是 tabs 的優(yōu)點(diǎn)之一是,這允許你做出比 “Tab” 制表符更加靈活的縮進(jìn)配置。
例如,我們可以將參數(shù)與左括號(hào)對(duì)齊,像下面這樣:
show(parameters,
aligned, // 左邊有 5 個(gè)空格
one,
after,
another
) {
// ...
}
即使是單個(gè)函數(shù)通常也被分割為數(shù)個(gè)邏輯塊。在下面的示例中,初始化的變量、主循環(huán)結(jié)構(gòu)和返回值都被垂直分割了:
function pow(x, n) {
let result = 1;
// <--
for (let i = 0; i < n; i++) {
result *= x;
}
// <--
return result;
}
插入一個(gè)額外的空行有助于使代碼更具可讀性。寫代碼時(shí),不應(yīng)該出現(xiàn)連續(xù)超過 9 行都沒有被垂直分割的代碼。
每一個(gè)語句后面都應(yīng)該有一個(gè)分號(hào)。即使它可以被跳過。
有一些編程語言的分號(hào)確實(shí)是可選的,那些語言中也很少使用分號(hào)。但是在 JavaScript 中,極少數(shù)情況下,換行符有時(shí)不會(huì)被解釋為分號(hào),這時(shí)代碼就容易出錯(cuò)。更多內(nèi)容請(qǐng)參閱 代碼結(jié)構(gòu) 一章的內(nèi)容。
如果你是一個(gè)有經(jīng)驗(yàn)的 JavaScript 程序員,你可以選擇像 StandardJS 這樣的無分號(hào)的代碼風(fēng)格。否則,最好使用分號(hào)以避免可能出現(xiàn)的陷阱。大多數(shù)開發(fā)人員都應(yīng)該使用分號(hào)。
盡量避免代碼嵌套層級(jí)過深。
例如,在循環(huán)中,有時(shí)候使用 ?continue
?指令以避免額外的嵌套是一個(gè)好主意。
例如,不應(yīng)該像下面這樣添加嵌套的 ?if
?條件:
for (let i = 0; i < 10; i++) {
if (cond) {
... // <- 又一層嵌套
}
}
我們可以這樣寫:
for (let i = 0; i < 10; i++) {
if (!cond) continue;
... // <- 沒有額外的嵌套
}
使用 if/else
和 return
也可以做類似的事情。
例如,下面的兩個(gè)結(jié)構(gòu)是相同的。
第一個(gè):
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
} else {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
}
第二個(gè):
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
return;
}
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
但是第二個(gè)更具可讀性,因?yàn)?nbsp;n < 0
這個(gè)“特殊情況”在一開始就被處理了。一旦條件通過檢查,代碼執(zhí)行就可以進(jìn)入到“主”代碼流,而不需要額外的嵌套。
如果你正在寫幾個(gè)“輔助”函數(shù)和一些使用它們的代碼,那么有三種方式來組織這些函數(shù)。
// 函數(shù)聲明
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
// 調(diào)用函數(shù)的代碼
let elem = createElement();
setHandler(elem);
walkAround();
// 調(diào)用函數(shù)的代碼
let elem = createElement();
setHandler(elem);
walkAround();
// --- 輔助函數(shù) ---
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
大多數(shù)情況下,第二種方式更好。
這是因?yàn)殚喿x代碼時(shí),我們首先想要知道的是“它做了什么”。如果代碼先行,那么在整個(gè)程序的最開始就展示出了這些信息。之后,可能我們就不需要閱讀這些函數(shù)了,尤其是它們的名字清晰地展示出了它們的功能的時(shí)候。
風(fēng)格指南包含了“如何編寫”代碼的通用規(guī)則,例如:使用哪個(gè)引號(hào)、用多少空格來縮進(jìn)、一行代碼最大長(zhǎng)度等非常多的細(xì)節(jié)。
當(dāng)團(tuán)隊(duì)中的所有成員都使用相同的風(fēng)格指南時(shí),代碼看起來將是統(tǒng)一的。無論是團(tuán)隊(duì)中誰寫的,都是一樣的風(fēng)格。
當(dāng)然,一個(gè)團(tuán)隊(duì)可以制定他們自己的風(fēng)格指南,但是沒必要這樣做?,F(xiàn)在已經(jīng)有了很多制定好的代碼風(fēng)格指南可供選擇。
一些受歡迎的選擇:
如果你是一個(gè)初學(xué)者,你可以從本章中上面的內(nèi)容開始。然后你可以瀏覽其他風(fēng)格指南,并選擇一個(gè)你最喜歡的。
檢查器(Linters)是可以自動(dòng)檢查代碼樣式,并提出改進(jìn)建議的工具。
它們的妙處在于進(jìn)行代碼風(fēng)格檢查時(shí),還可以發(fā)現(xiàn)一些代碼錯(cuò)誤,例如變量或函數(shù)名中的錯(cuò)別字。因此,即使你不想堅(jiān)持某一種特定的代碼風(fēng)格,我也建議你安裝一個(gè)檢查器。
下面是一些最出名的代碼檢查工具:
它們都能夠做好代碼檢查。我使用的是 ESLint。
大多數(shù)檢查器都可以與編輯器集成在一起:只需在編輯器中啟用插件并配置代碼風(fēng)格即可。
例如,要使用 ESLint 你應(yīng)該這樣做:
npm install -g eslint
? 命令(npm 是一個(gè) JavaScript 包安裝工具)安裝 ESLint。.eslintrc
? 的配置文件。下面是一個(gè) .eslintrc
文件的例子:
{
"extends": "eslint:recommended",
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
"indent": 2
}
}
這里的 "extends"
指令表示我們是基于 “eslint:recommended” 的設(shè)置項(xiàng)而進(jìn)行設(shè)置的。之后,我們制定我們自己的規(guī)則。
你也可以從網(wǎng)上下載風(fēng)格規(guī)則集并進(jìn)行擴(kuò)展。有關(guān)安裝的更多詳細(xì)信息,請(qǐng)參見 https://eslint.org/docs/user-guide/getting-started。
此外,某些 IDE 有內(nèi)建的檢查器,這非常方便,但是不像 ESLint 那樣可自定義。
本章描述的(和提到的代碼風(fēng)格指南中的)所有語法規(guī)則,都旨在幫助你提高代碼可讀性。它們都是值得商榷的。
當(dāng)我們思考如何寫“更好”的代碼的時(shí)候,我們應(yīng)該問自己的問題是:“什么可以讓代碼可讀性更高,更容易被理解?”和“什么可以幫助我們避免錯(cuò)誤?”這些是我們討論和選擇代碼風(fēng)格時(shí)要牢記的主要原則。
閱讀流行的代碼風(fēng)格指南,可以幫助你了解有關(guān)代碼風(fēng)格的變化趨勢(shì)和最佳實(shí)踐的最新想法。
重要程度: 4
下面的代碼風(fēng)格有什么問題?
function pow(x,n)
{
let result=1;
for(let i=0;i<n;i++) {result*=x;}
return result;
}
let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
{
alert(pow(x,n))
}
修復(fù)它。
你可以注意到以下幾點(diǎn):
function pow(x,n) // <- 參數(shù)之間沒有空格
{ // <- 花括號(hào)獨(dú)占了一行
let result=1; // <- = 號(hào)兩邊沒有空格
for(let i=0;i<n;i++) {result*=x;} // <- 沒有空格
// { ... } 里面的內(nèi)容應(yīng)該在新的一行上
return result;
}
let x=prompt("x?",''), n=prompt("n?",'') // <-- 從技術(shù)的角度來看是可以的,
// 但是拆分成 2 行會(huì)更好,并且這里也缺了空格和分號(hào) ;
if (n<=0) // <- (n <= 0) 里面沒有空格,并且應(yīng)該在本行上面加一個(gè)空行
{ // <- 花括號(hào)獨(dú)占了一行
// 下面的一行代碼太長(zhǎng)了,可以將其拆分成 2 行以提高可讀性
alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else // <- 可以像 "} else {" 這樣寫在一行上
{
alert(pow(x,n)) // 缺失了空格和分號(hào) ;
}
修改后的版本:
function pow(x, n) {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
let x = prompt("x?", "");
let n = prompt("n?", "");
if (n <= 0) {
alert(`Power ${n} is not supported,
please enter an integer number greater than zero`);
} else {
alert( pow(x, n) );
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: