【JavaScript 筆記】語句規則 - part 3

歡迎你點入本篇文章,本系列網頁程式設計,主要紀錄我個人自學的軌跡,另外也作為日後個人複習用。若你喜歡本篇文章,歡迎在文章底下點一顆愛心,或是追蹤我的個人公開頁~


分號(; Semicolons)

在 JS 中,分號 ; 用來標示一個語句的結束,類似中文的句號。

1
2
3
let name = "LukeTseng";    // 這是一個語句
let age = 21; // 這是另一個語句
console.log(name); // 這也是一個語句

ASI:自動插入分號機制

JS 中會有 ASI(Automatic Semicolon Insertion)的機制,當沒加分號時 JS 引擎會在解析時自動判斷在哪裡補上分號,這就是為什麼省略分號也不會報錯。

以下這兩個撰寫的方式都 ok:

1
2
3
4
5
let x = 10;
let y = 20;

let x = 10
let y = 20

ASI 的陷阱

ASI 不是萬能的,在某些情況下會誤判,導致其程式行為完全不符合預期:

1
2
3
4
5
6
7
function getUser() {
return
{
name: "LukeTseng"
}
}
console.log(getUser())

在上述程式碼中想要 return 一個 object,但是 return 後面就直接換行了,因此會輸出 undefined

image

原因是 JS 看到 return 後面直接換行,所以 ASI 就給他補上去分號,原本的程式碼就變成:

1
2
3
4
5
6
7
function getUser() {
return;
{
name: "LukeTseng"
}
}
console.log(getUser());

這樣就導致程式提前結束,正確的做法是把 { 往上移到 return 旁邊:

1
2
3
4
5
6
function getUser() {
return {
name: "Luke"
}
}
console.log(getUser())

然後就能得到正確結果了:

image

加不加分號?

身為一個長期、重度的 C/C++ 使用者,我的習慣是會加。

若要對一個初學者來說的話,加一下還是比較好,因為你不能保證 ASI 能看懂你的程式在幹嘛。

\ 拆行(Line Continuation)

當一行程式碼太長,可以用反斜線 \ 在字串內換行,讓程式碼更易讀,\ 必須是該行的最後一個字元,後面不能有任何空格。

1
2
3
4
5
6
7
8
// 不拆行
let msg = "我愛 JavaScript 我愛 JavaScript 我愛 JavaScript 我愛 JavaScript 我愛 JavaScript"

// 用 \ 拆行
msg = "我愛 JavaScript 我愛 JavaScript \
我愛 JavaScript 我愛 JavaScript 我愛 JavaScript"

console.log(msg)

用樣板字串(Template Literal)

ES6 的反引號字串可以直接跨行撰寫,更直覺也更安全,是現代的推薦做法:

1
2
3
4
5
6
7
let msg = `我愛 JavaScript 
我愛 JavaScript
我愛 JavaScript
我愛 JavaScript
我愛 JavaScript`

console.log(msg)

image

程式碼區塊(Code Blocks)

Code Blocks 是用一對大括號 {} 包起來的一段程式碼,用來把多個語句組成一個整體,常出現在函式、條件判斷、迴圈等結構中,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// if 語句的程式碼區塊
if (true) {
// 整個 { } 就是一個 Code Block
let x = 10
let y = 20
console.log(x + y) // 30
}

// 函式的程式碼區塊
function greet(name) {
// 這也是一個 Code Block
let msg = `哈囉,${name}!`
console.log(msg)
}

區塊的作用域(Scope)

使用 let / const 宣告的變數只在它所在的 {} 區塊內有效,出了區塊就消失:

1
2
3
4
5
{
let blockVar = "hello world!"
console.log(blockVar)
}
console.log(blockVar) // ReferenceError:blockVar is not defined

區塊可以巢狀(Nested)

{} 可以一層套一層,形成巢狀結構,內層可以存取外層的變數,但外層無法存取內層的變數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let outerVar = "外層"

{
let innerVar = "內層"
console.log(outerVar) // 外層
console.log(innerVar) // 內層

{
let deepVar = "最深層"
console.log(outerVar) // 外層
console.log(innerVar) // 內層
console.log(deepVar) // 最深層
}

console.log(deepVar) // deepVar is not defined
}

console.log(innerVar) // innerVar is not defined

註釋(Comments)

註釋是寫給人看的說明文字,JS 引擎執行時會忽略,不影響程式運作。

單行註釋 //

// 開始到該行結尾,全部都是註釋:

1
2
3
4
5
// 這是一行完整的註釋

let price = 100 // 這是行尾的 inline 註釋

// let oldCode = "這行程式碼被暫時停用"

多行註釋 /* */

/* 開始到 */ 結束,中間可以跨越任意多行:

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
這是多行註釋
通常用來說明比較複雜的邏輯
或者暫時停用一大段程式碼
*/

let result = /* 中間也可以插入 */ 42 + 8

/* 停用一整個函式
function oldFunction() {
console.log("這個函式暫時不用")
}
*/

須注意多行註釋不能巢狀,/* 裡面再寫 /* 會出錯:

1
2
3
/* 外層
/* 內層 */ 這個 */ 會被認為是外層的結尾,導致語法錯誤
*/

JSDoc 文件註釋(進階)

在函式前方用 /** */ 格式撰寫,可以讓 VS Code 等編輯器自動顯示函式說明,是業界標準的文件撰寫方式:

1
2
3
4
5
6
7
8
9
10
11
/**
* 計算兩數之和
* @param {number} a - 第一個數字
* @param {number} b - 第二個數字
* @returns {number} 兩數相加的結果
*/
function add(a, b) {
return a + b
}

// 之後當呼叫 add() 時 VS Code 會自動顯示上面的說明

image

四大規則整理

規則重點
分號 ;1. 建議每行都加;
2. return 後面的 { 一定不能換行
反斜線 \\1. 用於字串內的程式碼排版換行
2. 實際換行符號請用 \n 或樣板字串。
Code Block {}let/const 宣告的變數只在所在的 {} 有效
註釋1. 單行用 //
2. 多行用 /* */
3. 文件用 /** */

參考資料

JavaScript Statements | W3schools

Comments’ Usage and Best Practices in JavaScript - DEV Community

Automatic Semicolon Insertion (ASI) in JavaScript Made Simple

JavaScript Comment: Syntax, Usage, and Examples

Is It Necessary to Use Semicolons in JavaScript?

Lexical grammar - JavaScript | MDN

JavaScript 语句 | 菜鸟教程