陳述句和運算式
花括號的對齊方式
-
風格一
左括號放置在塊陳述句中第一句代碼的末尾
if (flag) { doSomething(); } else { doSomethingElse(); }解釋:這里所說的塊陳述句是包含條件(回圈)控制陳述句的,比如這個例子中,塊陳述句的第一句代碼實際是if陳述句所在得到行
這種風格繼承自Java
-
風格二
花括號的第二種對齊風格是將制作花括號放置在塊陳述句首行的下一行
if (flag) { doSomething(); } else { doSomethingElse(); }這種風格是隨著C#流行起來的,因為Visual Studio強制使用這種對齊方式
塊陳述句間隔
-
風格一
陳述句名、圓括號和左花括號之間沒有空格間隔
if(flag){ doSomething(); }看起來較為緊湊
-
風格二
括左圓括號之前和右圓括號之后各添加一個空格
if (flag) { doSomething(); } -
風格三
左圓括號后和右圓括號前各添加一個空格
if ( flag ) { doSomething(); }
switch陳述句
縮進
-
風格一
switch(condition) { case "first": // 代碼 break; case "second": // 代碼 break; default: // 代碼 }- 每條case陳述句相對于switch關鍵字都縮進一個層級
- 從第二條case陳述句開始,每條case陳述句前后都各有一個空行
-
風格二
switch(condition) { case "first": // 代碼 break; case "second": // 代碼 break; default: // 代碼 }- 每條case陳述句相對于switch關鍵字都沒有縮進
- 每條case陳述句前后沒有空行
case陳述句的“連續執行”
“執行完一個case后連續執行下一個case”,這是否是一種廣被認可的實踐,但也是倍受爭議的一個問題,不小心省略case末尾的break是很多bug的罪魁禍首,因此Douglas Crockford提出所有的case都應當以break、retur或throw做結尾,有很多人認為case的連續執行是一種可以接受的編程方法,只要程式邏輯非常清晰即可
switch(condition) {
// 明顯的依次執行
case "first":
case "second":
// 代碼
break;
case "third":
// 代碼
/* fail through */
default:
// 代碼
}
這段switch陳述句中,有兩個明顯的“連續執行”,程式執行完成第一個case后會繼續執行第二個case,我們認為這種邏輯是合理的,因為第一個case陳述句中并沒有需要執行的陳述句,也沒有任何其他陳述句將這兩個case陳述句分割開
第二個例子是case "third"執行后繼續執行default里的邏輯,這個程序已經在注釋中明確說明了,這是程式撰寫者故意為之,這段代碼由于加了注釋,我們可以清晰地看到case陳述句何時繼續執行
default
switch陳述句另一個需要討論的議題是,是否需要default,很多人認為不論何時都不應該省略default,哪怕default什么也不做,
switch(condition) {
case "first":
// 代碼
break;
case "second":
// 代碼
break;
default:
// default中沒有邏輯
}
作者更傾向于在沒有默認行為的且寫了注釋情況下省略default
switch(condition) {
case "first":
// 代碼
break;
case "second":
// 代碼
break;
// 沒有default
}
with陳述句
with陳述句可以更改包含的背景關系決議變數的方式,通過with可以用區域變數和函式的形式來訪問特定的物件的屬性和方法,這樣就可以將物件前綴統統省略掉,如果一段代碼重書寫了很多物件成員,則可以使用with陳述句來縮短這段代碼,例如:
var book = {
title: "可維護的JavaScript",
author: "Nicholas C. Zakas"
};
var message = "The book is ";
with (book) {
message += title;
message += " by " + author;
}
在這個例子中,with陳述句花括號內的代碼中的book的屬性都是通過區域變數來讀取的,以增強識別符號的決議,問題是我們很難分辨title和author出現在哪個位置,也很難分辨出message到底是區域變數還是book的一個屬性,實際上這種困惑對開發者的影響更甚,JavaScript引擎和壓縮工具無法對這段代碼進行優化,因為它們無法猜出代碼的正確含義,
在嚴格模式下,with是被明令禁止的,如果使用就會報語法錯誤
for回圈
for回圈有兩種可以更改回圈的執行程序(除了使用return和throw陳述句),
break
第一種方式是使用break陳述句,不管所有的回圈迭代又沒有執行完畢,使用break總是可以立即退出回圈,
var values = [1, 2, 3, 4, 5, 6, 7, 8],
i, len;
for (i = 0, len = values.length; i < len; i++) {
if (i == 2) {
break; // 迭代不會繼續
}
process(values[i]);
}
這里的回圈體只會執行兩次,然后在第三次執行 process()之前就終止回圈了,盡管values陣列中的元素超過了三個,
continue
第二種更改回圈執行程序的方法是使用continue,continue陳述句可以立即退出(本次)回圈,而進入下一次回圈迭代
var values = [1, 2, 3, 4, 5, 6, 7, 8],
i, len;
for (i = 0, len = values.length; i < len; i++) {
if (i == 2) {
continue; // 跳出本次迭代
}
process(values[i]);
}
這里回圈體將執行兩次,跳過第三次迭代,而后進入第四次迭代,回圈繼續執行直到最后一次迭代(如果中途不再會打斷的話)
Crockford的編程規范不允許使用continue,他主張代碼中與其使用continue不如使用條件陳述句,比如說上一個陳述句修改為
var values = [1, 2, 3, 4, 5, 6, 7, 8],
i, len;
for (i = 0, len = values.length; i < len; i++) {
if (i != 2) {
process(values[i]);
}
}
作者推薦盡可能避免使用continue,但也沒有理由完全禁止使用,它的使用應當根據代碼可讀性來決定
for-in回圈
for-in回圈是用遍歷物件屬性的,不用定義任何控制條件,回圈將會有條不紊地遍歷每個物件屬性,并回傳屬性名而不是值,
for-in回圈有一個問題,就是他不僅變數物件的實體屬性,同樣還遍歷從原型鏈上繼承來的屬性,當遍歷自定義物件的屬性時,往往會因為意外結果而終止,處于這個原因,最好使用hasOwnProperty()方法來為for-in回圈過濾出實體屬性,
var prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
console.log("property name is " + prop);
console.log("property value is " + object[prop]);
}
}
作者推薦使用hasOwnProperty()檢測,如果是想遍歷查找原型鏈上的值可以補充注釋
var prop;
for (prop in object) { // 包含對原性鏈的遍歷
console.log("property name is " + prop);
console.log("property value is " + object[prop]);
}
錯誤:使用for-in遍歷陣列
var values = [1, 2, 3, 4, 5, 6, 7, 8],
i;
for (i in values) {
process(values[i]);
}
使用for-in遍歷陣列會造成潛在錯誤,記住,for-in回圈是用來對實體物件和原型鏈中的鍵(key)做遍歷的,而不是用來遍歷包含數字索引的陣列的,因此for-in回圈不應當用于這種場景
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/234760.html
標籤:其他
上一篇:學習 ES11(ES2020)
