談 JavaScript 表達式與陳述式的差異:學習 React 帶來的啟發

更新於 發佈於 閱讀時間約 13 分鐘

面對 JavaScript 核心觀念時,總是感覺似懂非懂,於是就這樣不求甚解地繼續學習程式。但該面對的最終還是得面對,有些東西總會像鬼一樣,沒解決就會陰魂不散的回來,表達式 (expression) 與陳述式 (statement) 這兩個好兄弟就是其中之一。

還好有 Josh Comeau 深入淺出的文章,把我從五里霧中拉了出來,應 該 吧。這篇文章將以此基礎,就我的理解加其他輔助資料撰寫而成,如有錯誤還煩請指教。那就廢話少說開始吧。

Photo Credit: Ferenc Almasi, Unsplash

Photo Credit: Ferenc Almasi, Unsplash


什麼是表達式?

如果要說表達式是什麼?最簡單的回答就是「能夠產生值的程式碼」,它可以是:

  • 任何的資料型別,像是
    • 數字: 168
    • 字串:"string"
    • 布林:truefalse
    • 陣列:["arr", "ray", "yee"]
    • 物件:{ type: "object" }
  • 運算子產生的結果,常見的有
    • 賦值運算子:=
      → 回傳「所賦予的值」
    • 算數運算子:+-*/%
      → 回傳「運算後的結果」
    • 比較運算子:><=====
      → 回傳「布林值」
    • 邏輯運算子:||&&!
      • ||:回傳「布林值」(「或」的判斷),或「第一個真值」
      • &&:回傳「布林值」(「且」的判斷),或「第一個假值」
      • !:回傳「翻轉後的布林值結果」
    • 條件(三元)運算子:hasValue ? "expressions" : "statements"
      → 依據條件真假(hasValue 處),決定回傳值:
      若為,回傳「冒號之前的值」;若為,回傳「 冒號之後的值」
  • 執行函式後產生的結果,以下有幾種情況:
// 1. 有明確的回傳值
function execFnHasReturn() {
console.log("This function will return something after execution");
return "I am returned value";
}
console.log(execFnHasReturn()); // 執行後回傳 "I am returned value"

// 2. 有 return 但沒有回傳值
function execFnEmptyReturn() {
console.log("This function will return 'undefined' value after execution");
return;
}
console.log(execFnEmptyReturn()); // 執行後回傳 undefined

// 3. 沒有 return
function execFnNoReturn() {
console.log("This function will return 'undefined' value after execution");
}
console.log(execFnNoReturn()); // 執行後回傳 undefined

→ 無論回傳值是否為 undefined,都不改執行函式是表達式的事實

  • 調用方法的結果,方法本質上也是函式的一種,回傳值會依方法而定:
["apple","banana"].push("orange");       // 回傳 3,新增項目後陣列的長度​
[1, 2, 3].forEach(i => console.log(i)); // 回傳 undefined
[3, 1, 2].sort() // 回傳 [1, 2, 3],修改後的陣列
"yee".toUpperCase() // 回傳 "YEE"
  • 其他:變數、正規表達式、函式表達式……


看了這麼多表達式的型態,可以歸納幾個重點:

  1. 表達式可以透過運算子,形成更複雜的表達式,例如:
    1. 88 / (1.88 * 1.88)
      88 / (1.88 * 1.88)(1.88 * 1.88)881.88 都是表達式
    2. hasValue ? "expressions" : "statements"​
      hasValue"expressions""statements"​ 都是表達式
  2. 會回傳值,即便該值是 undefined,也是表達式


什麼是陳述式?

JavaScript 是由一系列陳述式組成,陳述式不會產生值,它的作用在於告訴瀏覽器「該執行什麼動作」以及「控制程式的流程走向」,主要分為以下幾種:

  • 宣告:告訴瀏覽器要為宣告的內容分配記憶體空間
    • 變數的宣告:用 varletconst 關鍵字來宣告變數
    • 函式的宣告:用 function 來宣告函式
    • 類別的宣告:用 class 來宣告類別
  • 流程控制:告訴瀏覽器執行程式碼的流程該怎麼走
    • 條件判斷:if...elseswitchwhile/do...while
    • 迴圈執行:for、 ​for...infor...of
    • 語句中斷、回傳或跳轉:return(throw)、breakcontinue
    • 例外處理:try...catch(& finally)
  • 模組相關:importexport
  • 其他:debugger(中斷執行)、async/await(非同步處理)、{ }(區塊)…

陳述式透過這些關鍵字建立出一個敘述的邏輯架構,但要有內容才是完整的陳述句,而這些內容,則需要靠表達式來提供,例如,

// if 陳述式
if (/* 表達式 */) {
//...
}

// 範例
if (age >= 18 && hasID) {
// ...
}

// 迴圈陳述式
for (/* 初始化;條件;更新 */) {
// ...
}
// -> 條件、更新須為表達式
// -> 初始化可用變數宣告或表達式,以 let 宣告可限定作用域

// 範例
for (let i = 0; i < array.length; i++) {
// ...
}

// switch 陳述式
switch (/* 表達式 */) {
case /* 表達式 */:
// ...
}

// 範例
switch (status) {
case "success":
// ...
}

同時,我們可以透過宣告變數,將表達式的值存入該變數之中:

let num = 168;
let str = "string";
let isBool = true;
let arr = ["arr", "ray", "yee"];
let obj = { type: "object" };
let text = "yee".toUpperCase()


學習 React 帶來的啟發

撰文當下,我對 React 的理解還不夠深入,不過在學習的過程中,似乎讓我對表達式與陳述式的差別更加清明了。

在 React 中,我們會透過一種叫做 JSX 的語法,在 JavaScript 中撰寫 HTML 的結構。JSX 能夠讓我們可以在 HTML 的結構中,透過大括號 {} 將 JavaScript 程式碼插入 HTML 裡。

不過,這個大括號並非毫無限制,我們並沒有辦法隨心所欲地放入任何的 JavaScript 程式碼,我們看看下方兩個 JSX 的例子,同樣是處理條件邏輯,但其中一個會出錯:

  • 大括號內用 if...else 語句(陳述式):會出現語法錯誤
function DisplayExamResult({ examScore }){
return (
<div>
{if (examScore >= 60){
return "Congrats! You passed!"
} else {
return "What a pity, you failed!"}}
</div>
);
}
  • 必須使用「三元運算子」(表達式)處理條件的邏輯:
function DisplayExamResult({ examScore }){
return (
<div>
{examScore >= 60 ? "Congrats! You passed!" : "What a pity, you failed!"}
</div>
);
}

一樣是條件邏輯,我們只能在大括號內放入表達式,為什麼呢?


JavaScript 作為一種……語言?

拿 Comeau 的比喻來形容(我也覺得這個比喻極讚!),JSX 的大括號 {} 就像是 HTML 模板中的插槽,我們需要在這個插槽中放入「表達式」,而不是「陳述式」。因為只有表達式才會產生具體的值,才能變成實際的東西被渲染到畫面上。

雖然可能不是很精確,不過用英文基礎的「主詞-動詞-受詞」(S-V-O) 句型來說,如果挖空主詞、受詞的位置,這個空格可以用很單純的名詞填補,你也可以套上形容詞、甚至形容詞子句讓這個名詞變得更加複雜,但最終你填上的東西,還是得屬於名詞類,因為在英文文法中,主詞、受詞只能是名詞類的東西。

### S V O 句型
The woman wrote a program.

### 將 S、 O 挖空
{ S } wrote { O }​

### ​用更複雜的 S、O 撰寫
The elegant **woman** you saw yesterday
wrote
a complicated **program** by herself to change people's lives.

表達式的撰寫方式可能有上百種,但我覺得它所傳出來的「值」就有點像是這種概念。回到 JSX 的大括號裡為什麼不能放 if...else 語句的問題,用英文句型的思考來回答,就是詞類不相符。

有了這個感覺,突然好像對我們時常稱呼 JavaScript 的名詞——程式語言——更加有所體悟。

為什麼會稱 JavaScript 為「語言」呢?相對的,HTML、CSS 就好像沒那麼常被這樣形容。就我穿鑿附會的想像,原因可能是:

JavaScript 和人類語言一樣,能夠歸納出固定的語法結構和規則

我想到的是,寫 JavaScript 時,之所以像是與瀏覽器溝通,也許就是表達式與陳述式相互作用的結果。陳述式提供句子的結構,控制語意的走向;而表達式則像是句子中的片語,可以產生一個具體的值,填補結構中的空白,才能賦予程式碼意義,進而向瀏覽器表達出我們的目的。


總結

以免被我的老人廢話給稀釋重點,最後再來複習一下表達式與陳述式的主要特色吧:

  • 表達式
    • 執行時會產生值
    • 用於預期會是值的地方(插槽),例如 JSX 的大括號內、變數賦值,以及函式的參數等等
    • 可以與其他表達式結合,產生更複雜的表達式
  • 陳述式
    • 告訴瀏覽器執行特定動作
    • 形塑程式碼的結構,控制程式碼流程走向
    • 經常與表達式一起使用,但本身不會產生值


希望這篇文章能夠幫助到你,如有錯誤也煩請指教,感謝你的閱讀。


參考資料

avatar-img
0會員
1內容數
2024 年 7 月開始的「肝 code 人生」,2025 年 1 月撰寫第一篇程式筆記
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
JSDoc 全名是 JavaScript Documentation,顧名思義是為 JavaScript 所使用的 API 文件,在程式碼內透過註解的方式撰寫,運行後 JSDoc 會自動掃描註解內容,並生成一份網頁版的文件,對於沒有使用 Typescript 開發的專案,也
Thumbnail
一般在使用 TypeScript 的時候,大家都有遇過定義列舉資料的情境吧。 不過不管是 enum 和 literal 的方式其實都有些小缺點,以下推薦一個個人認為體驗更好的方式。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
JavaScript (簡稱 JS) 是具有一級函數的輕量級、直譯式或即時編譯的程式語言。它因為用作網頁的腳本語言而大為知名,但也用於許多非瀏覽器的環境,像是 Node.js 等。由於 JavaScript 語法上的一些缺點,軟體工程師們又設計出了 CoffeeScript、TypeScript 和
Thumbnail
JavaScript是一種具有動態型別、弱型別、原型繼承等特性的高級腳本語言,應用範圍廣泛,包括前端開發、後端開發、移動應用等。它被各種公司和開源社區廣泛使用。學習JavaScript需要掌握ECMAScript標準、異步編程、模塊系統等知識。
※ 函式基礎介紹: ※ JavaScript 特殊的函式特性: 函式可以當成值來傳遞 (可以放進變數或放進物件) 函式可以當成函式的參數 callback - 在特定事件中觸發函式 (非同步特性) ※ 函式的基本寫法: ※ 調用 (invoke) 函式: "調用" 意指呼叫或執行
前言: 一直想要把自己的學習筆記整理整理,至少在寫下筆記的時候,也能釐清觀念。 結果拖延到現在,終於要提筆了,不知道能堅持多久(???)。
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
JSDoc 全名是 JavaScript Documentation,顧名思義是為 JavaScript 所使用的 API 文件,在程式碼內透過註解的方式撰寫,運行後 JSDoc 會自動掃描註解內容,並生成一份網頁版的文件,對於沒有使用 Typescript 開發的專案,也
Thumbnail
一般在使用 TypeScript 的時候,大家都有遇過定義列舉資料的情境吧。 不過不管是 enum 和 literal 的方式其實都有些小缺點,以下推薦一個個人認為體驗更好的方式。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
JavaScript (簡稱 JS) 是具有一級函數的輕量級、直譯式或即時編譯的程式語言。它因為用作網頁的腳本語言而大為知名,但也用於許多非瀏覽器的環境,像是 Node.js 等。由於 JavaScript 語法上的一些缺點,軟體工程師們又設計出了 CoffeeScript、TypeScript 和
Thumbnail
JavaScript是一種具有動態型別、弱型別、原型繼承等特性的高級腳本語言,應用範圍廣泛,包括前端開發、後端開發、移動應用等。它被各種公司和開源社區廣泛使用。學習JavaScript需要掌握ECMAScript標準、異步編程、模塊系統等知識。
※ 函式基礎介紹: ※ JavaScript 特殊的函式特性: 函式可以當成值來傳遞 (可以放進變數或放進物件) 函式可以當成函式的參數 callback - 在特定事件中觸發函式 (非同步特性) ※ 函式的基本寫法: ※ 調用 (invoke) 函式: "調用" 意指呼叫或執行
前言: 一直想要把自己的學習筆記整理整理,至少在寫下筆記的時候,也能釐清觀念。 結果拖延到現在,終於要提筆了,不知道能堅持多久(???)。
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。