Category: Programming

  • 告別「加號」地獄:JavaScript 字串革命與 Template Literals 的魔法

    前言:關於「拼貼」的惡夢

    假想你正坐在小學時的美勞課教室裡,美術老師發給全班每位同學各一張畫紙,並且要求製作一張「自我介紹」的海報。內容的製作方式規定用最原始的剪貼方法完成,海報內容的製作過程大概是這樣的:

    1. 先在報紙找到並剪下「我」這個字
    2. 拿起膠水把「我」這個字貼到畫紙
    3. 接著再剪下「叫做」這個字,貼上去
    4. 找不到合適的字,就改用彩色筆寫上自己的名字「王小明」
    5. 然後繼續剪下「,今年」這幾個字……

    這種製作過程鐵定弄得滿手都是膠水不說,如果不小心貼歪了、或者字與字中間忘記留空白,整張海報就毀了。在 2015 年之前的 JavaScript 世界(ES5 時代),程式設計師處理文字(String)的方式,就很類似這種原始的剪貼方式,這種技巧被稱之為「字串串接(String Concatenation)」。

    自從 ES6 版本發布後,JavaScript 獲得一項神級裝備:Template Literals(樣板字面值),俗稱樣板字串。它就像是一張設計好的「數位表單」,你只需要在空格裡填字,其他的格式電腦自動幫你處理好。我們就用大學生的日常情境,來聊聊這個讓 Web 開發者從地獄飛升到天堂的語法。

    第一章:認識新朋友「反引號」

    1. 鍵盤上的邊緣人

    首先,我們要尋找開啟魔法的鑰匙。 低頭看看鍵盤左上角 Esc 鍵的下面、數字 1 鍵的左邊,有一個長得像毛毛蟲的符號 ~,在那個鍵上,還存在著一個不起眼的小撇號 `。這個小撇號有個英文名字叫做 Backtick,中文則叫它「反引號」。

    • 舊時代的字串:使用單引號 ‘ ‘ 或雙引號 ” “
    • 新時代的樣板字串:必須使用反引號 ` ` 包起來

    2. 為什麼要換符號

    我自己當初是蠻好奇:「單引號用得好好的,幹嘛多學一個符號?」深入研究才逐漸地理解因為單引號和雙引號在處理「文字裡的引號」時很痛苦,假設你要在螢幕上印出這句話:I’m a student at “NTU”.

    如果你用單引號寫:

    JavaScript
    
    // 錯誤示範
    let str = 'I'm a student...'; // 程式爆掉!

    電腦讀到 I 後面的單引號,就會以為字串結束了,後面的 m 會被當成亂碼。你必須用反斜線 \ 來轉譯(Escape),寫成 ‘I\’m a student…’。

    但如果你用反引號

    JavaScript
    
    // 完美示範
    let str = `I'm a student at "NTU".`;

    在反引號的世界裡,單引號和雙引號都是普通的文字,完全不需要特殊處理。這就像是給了文字一個專屬的 VIP 包廂,外面怎麼吵都影響不了裡面。

    第二章:填空遊戲的藝術「變數嵌入 (Interpolation) 」

    這是 Template Literals 最強大的功能,也是它被稱為「樣板」的原因。

    1. 舊時代的「加號」地獄

    假設你在寫一則社群網站的歡迎訊息,內容包含兩個變數:name 和 count(代表通知數量)。

    舊寫法:

    JavaScript
    
    const name = "傑哥";
    const count = 5;
    
    // 注意那個 '+' 和裡面無數個引號
    const msg = "哈囉," + name + "!您目前有 " + count + " 則新通知。";

    這種寫法有幾個致命缺點:

    1. 容易寫錯: 你很容易忘記加空格,變成 哈囉,傑哥!您目前有5則新通知。(黏在一起)
    2. 閱讀困難: 程式碼被切得支離破碎,很難一眼看出這句話原本長怎樣
    3. 手很酸: 你要一直按 Shift 鍵輸入雙引號或加號

    2. 新時代的 ${} 魔法

    讓我們看看樣板字串怎麼做?其實有點像是在玩填字遊戲。

    新寫法:

    JavaScript
    
    const name = "傑哥";
    const count = 5;
    
    // 乾淨、直觀
    const msg = `哈囉,${name}!您目前有 ${count} 則新通知。`;

    看到那個 ${} 了嗎?這就是魔法所在。

    • 規則: 在反引號 `…` 的範圍內,只要看到 ${…},電腦就會自動把花括號裡面的變數「算出來」,然後把結果填進去。

    這就像是你在寫一張邀請卡:「親愛的 ________,誠摯邀請您參加…」,你不需要把紙剪開再黏貼名字,只需要在橫線上填寫名字就好。這讓程式碼的可讀性提升了一個檔次,你寫的程式碼長得就跟輸出的結果一模一樣。

    第三章:詩人的救贖「多行字串 (Multi-line Strings) 」

    1. 舊時代的 \n

    想像你要在網頁上印出一首唐詩或者一段分行的地址。在以前,JavaScript 的字串是不允許直接換行的。如果你在程式碼裡按下 Enter 鍵,程式會報錯,你必須使用特殊的換行符號 \n (Newline):

    JavaScript
    
    // 舊寫法:醜陋且難以排版
    const poem = "床前明月光,\n" +
                 "疑是地上霜。\n" +
                 "舉頭望明月,\n" +
                 "低頭思故鄉。";

    這種用法就像從使用打字機寫詩保留下來的習慣,每次換行都要手動推一下機器,非常不直覺。

    2. 新時代:想換行就換行

    Template Literals 完全保留程式碼中的排版,如果你在反引號裡按下了 Enter,輸出的字串裡就會真的有一個 Enter。

    JavaScript
    
    // 新寫法:所見即所得
    const poem = `
      床前明月光,
      疑是地上霜。
      舉頭望明月,
      低頭思故鄉。
    `;

    這對於程式開發者寫 HTML 結構或是 SQL 查詢語句時非常有用,你可以把程式碼排版得漂漂亮亮,不用擔心被擠成一坨。

    第四章:字串裡的微型計算機「表達式嵌入」

    還記得剛剛說的 ${} 嗎?它不只能放變數,其實也可以放任何 JavaScript 的表達式(Expression)

    1. 什麼是表達式

    簡單來說,只要能「算出一個值」的東西,都叫表達式,舉例:

    • 1 + 1 是表達式(算出 2)
    • age >= 18 是表達式(算出 true 或 false)
    • Math.max(10, 20) 是表達式(算出 20)

    2. 在字串裡算數學

    假設你從網路買了 3 本書,每本 200 元,你想印出總價。

    JavaScript
    
    const price = 200;
    const quantity = 3;
    
    // 直接在 ${} 裡面做乘法!
    const total = `您購買了 ${quantity} 本書,總金額是 ${price * quantity} 元。`;
    
    console.log(total); // 印出:您購買了 3 本書,總金額是 600 元。

    你不需要先在外面宣告一個 let sum = price * quantity,直接在字串裡算就好,這就像是你的收據紙上內建了一台計算機。

    3. 字串裡的邏輯判斷「三元運算子 (Ternary Operator) 」

    三元運算子是一種進階撰寫技巧,在 Web 開發超級常用。假設你要顯示使用者的登入狀態,

    JavaScript
    
    const isLogin = true;
    // 如果 isLogin 是 true,顯示「歡迎回來」;否則顯示「請先登入」
    const status = `系統訊息:${ isLogin ? "歡迎回來" : "請先登入" }`;

    這讓你的文字具有了「智慧」,能根據狀況自動改變內容,而不用寫一大堆 if…else。

    第五章:前端開發的神器「HTML 樣板」

    HTML 樣板大概是 Template Literals 對 Web 開發貢獻最大的地方,假設你是系學會網站的管理員,打算把「幹部名單」顯示在網頁上。如果不使用現代網頁開發框架,只用原生 JavaScript 撰寫網頁的程式碼,你極有可能會寫到想哭出來。

    舊寫法(字串拼接地獄):

    JavaScript
    
    const member = { name: "小華", job: "公關長" };
    const html = "<div class='card'>" +
                 "  <h2>" + member.name + "</h2>" +
                 "  <p>" + member.job + "</p>" +
                 "</div>";
    // 只要少一個引號,網頁就破圖

    新寫法(樣板字串):

    JavaScript
    
    const member = { name: "小華", job: "公關長" };
    
    // 就像在寫真的 HTML 一樣!
    const html = `
      <div class="card">
        <h2>${member.name}</h2>
        <p>${member.job}</p>
      </div>
    `;

    看到差別了嗎?新寫法不僅保留 HTML 的縮排結構,讓我們一眼就能看出網頁長什麼樣子。而且,變數插入的位置也一目了然,這對於初學者理解「JavaScript 如何控制網頁」是非常好的寫作方法。

    第六章:進階魔法「標籤樣板字面值 (Tagged Templates) 」

    最後,我們來介紹一個聽起來很學術,但其實很有趣的功能:Tagged Templates。 這有點像是你把字串丟進一座「加工廠」裡,出來的東西會變不一樣,它的語法長這樣:

    JavaScript
    
    function highlight(strings, ...values) {
      // 這裡可以寫邏輯來處理字串...
      // 例如把變數都加上紅色的 HTML 標籤
    }
    
    const name = "小明";
    const action = "睡過頭";
    // 注意!highlight 後面直接接反引號,沒有括號!
    const result = highlight`昨天 ${name} 又 ${action} 了`;

    雖然初學者可能暫時用不到這個,但如果你未來學習 React 這個熱門框架,你會看到一個很有名的套件叫 styled-components,它就是用這種魔法來寫 CSS 樣式的。

    結語:從工具看見思維的轉變

    JavaScript 的 Template Literals 不僅僅是一種「新語法」,也代表程式語言設計思維的轉變:從「配合電腦」轉向「配合人類」

    • 以前: 我們為了配合電腦的邏輯,把一句完整的話拆得支離破碎,用一堆加號黏起來。
    • 現在: 電腦配合我們的閱讀習慣,讓我們用最自然的語氣、最直觀的排版來撰寫程式碼。

    對於開發者來說,這就像是從手寫筆記進化到使用 Notion 或 iPad 筆記一樣。內容本質可能沒變,但工具的便捷性會讓你更願意去創作、去開發。下一次,當你在寫 JavaScript 或者試著做自己的個人網站時,看到那個要按 Shift 才能打出來的 + 號,請停下來想一想: 「是不是該按下鍵盤左上角的那個魔法鍵 ` 了?」

    擁抱 Template Literals,讓你的程式碼像詩一樣優雅吧!

  • 程式碼的「拆禮物」哲學:一次搞懂 JavaScript 的解構賦值 (Destructuring)

    前言:從網購包裹說起

    在網路上大買特買一番的幾天後,物流寄來一個巨大紙箱,裝著你買的新球鞋、一件帽 T,還有一組藍牙耳機。每次要聽音樂時,你會把整個大紙箱揹在身上,把頭伸進紙箱裡找耳機嗎?當然不會!你會做的是「開箱」:把球鞋放到鞋櫃、帽 T 掛進衣櫥、耳機拿出來放在桌上,簡言之,你把原本都在「同一個箱子」裡的東西,拿出來變成「獨立」的物品,方便你隨手取用。

    2015 年之前的 JavaScript 世界裡(稱為 ES5 時代),Web 設計師就像是揹著大紙箱的人,每次要用資料,都要輸入一長串的路徑去「箱子」裡撈。自從 ES6 版本發布後,JavaScript 引入一個革命性的語法:Destructuring Assignment(解構賦值),它就像是一把美工刀,讓我們能優雅地劃開資料的膠帶,把裡面的數值「瞬間」拿出來變成獨立的變數。今天,我們就用大學生活的日常拆解這個讓所有 Web 開發者都愛不釋手的語法糖。

    第一章:為什麼我們需要「解構」

    我們先來看看「沒有解構」的世界有多麻煩。

    1. 痛苦的點名時間

    假設你在寫一個社團成員的網頁,伺服器傳來一份社員資料,這是一個「物件(Object)」,部分內容如下:

    JavaScript
    
    // 這是我們拿到的一個資料包(Object)
    const student = {
      name: "王小明",
      age: 20,
      department: "資管系",
      gpa: 3.8
    };

    在 ES5 時代,如果想把這個同學的資訊印在螢幕上,必須這樣寫:

    JavaScript
    
    // ES5 時代寫法
    const name = student.name;
    const age = student.age;
    const dept = student.department;
    console.log(name + " 是 " + dept + " 的學生");

    發現了嗎?你一直重複寫 student.、student.、student.。這就像是每叫一次王小明,都要連名帶姓加上就讀科系喊一遍:「資管系的王小明請回答」、「資管系的王小明今年幾歲」。這種用法不僅累人,程式碼看起來也很雜亂。

    2. 解構賦值的魔法

    我們用「解構賦值」重寫這段程式碼,這就是把東西從箱子裡「拿出來」的瞬間:

    JavaScript
    
    // 新時代的寫法:解構!
    const { name, department } = student;
    console.log(name + " 是 " + department + " 的學生");

    這行 const { name, department } = student; 做了什麼事?它告訴電腦:「請去 student 這個箱子裡,找到標籤寫著 name 和 department 的東西,然後把它們拿出來,直接變成兩個獨立變數,名字也叫 name 和 department。」

    就這樣,一行搞定。這就是解構的核心精神:DRY (Don’t Repeat Yourself),別做重複的事。

    第二章:陣列解構 (Array Destructuring) 

    JavaScript 裡有兩種最主要的資料容器:陣列 (Array)物件 (Object),解構這兩種容器的邏輯稍有不同,先從比較簡單的「陣列」講起。

    1. 陣列就像「排隊」

    陣列裡的資料是有順序的,就像你去學生餐廳的自助餐買便當時,店員會依序幫你夾菜:第一格是飯,第二格是青菜,第三格是雞腿,最後附上一瓶養樂多。

    JavaScript
    
    // 一個陣列,代表今天的便當
    const lunchBox = ["白飯", "高麗菜", "炸雞腿", "養樂多"];

    2. 依序領取

    如果我們要用解構的方式把便當裡的東西拿出來,必須使用 方括號 [](注意,這裡的方括號在等號左邊,代表解構,不是創造新陣列)。

    JavaScript
    
    // 陣列解構
    const [staple, vegetable, meat, drink] = lunchBox;
    console.log(meat); // 印出:炸雞腿

    這裡的邏輯是「對號入座」:

    • 變數 staple 對應到 lunchBox 的第 1 個位置(Index 0)。
    • 變數 vegetable 對應到第 2 個位置。
    • 以此類推。

    重要觀念: 在陣列解構中,變數的名字不重要,順序才重要。 你高興的話,可以把雞腿取名為 myLove:

    JavaScript
    
    const [item1, item2, myLove] = lunchBox;
    console.log(myLove); // 還是印出:炸雞腿

    3. 跳過不想吃的菜

    假設今天你不想吃菜,只想要飯和雞腿,怎麼辦?我們可以用「留白」的方式跳過中間的項目。

    JavaScript
    
    // 使用逗號跳過中間的元素
    const [rice, , chicken] = lunchBox;
    console.log(rice);    // 白飯
    console.log(chicken); // 炸雞腿
    // 高麗菜就這樣被忽略了,不會產生變數佔用記憶體

    這在 Web 開發中很常見,有時候網頁網址分割後會產生一堆片段,我們只需要第一段和最後一段,中間的就可以用這種方式略過。

    第三章:物件解構 (Object Destructuring)

    接下來是 Web 開發中最常使用的 物件解構

    1. 物件就像「工具箱」

    物件裡的資料沒有順序,但是有名字(Key)。這就像筆袋或工具箱,你找原子筆不是看它在「左邊數來第三支」,而是看它是不是原子筆。

    JavaScript
    
    const iphone = {
      model: "iPhone 17",
      storage: "256GB",
      color: "Black",
      price: 29900
    };

    2. 認名不認人

    物件解構使用的是 花括號 {}

    JavaScript
    
    // 物件解構
    const { price, model } = iphone;
    console.log(model); // iPhone 17
    console.log(price); // 29900

    注意到什麼了嗎?我在解構的時候,把 price 寫在 model 前面。 沒關係,完全不影響! 因為物件解構是看「標籤名稱」,電腦會去 iphone 物件裡找 price 這個屬性,找到後塞給變數 price,順序怎麼換都沒差。

    3. 幫變數取綽號(Renaming)

    有時候伺服器傳回來的資料名字很爛,或者跟你的程式碼衝突。例如,伺服器給你的資料叫 class,但在 JavaScript 裡 class 是保留字(不能當變數名),這時候我們可以在解構的當下幫它改名

    JavaScript
    
    const user = {
      id: 9527,
      name: "唐伯虎",
      class: "高級伴讀書僮" // 假設後端傳來這個爛名字
    };
    
    // 語法: { 原本的名字 : 新的名字 }
    const { name, class: jobTitle } = user;
    console.log(jobTitle); // 印出:高級伴讀書僮
    
    // console.log(class); // 這會報錯,因為 class 變數不存在,它已經被改名成 jobTitle 了

    這招在串接 API時超級好用,例如 Google Maps API 可能回傳 lat,但你的程式碼習慣用 latitude,你就可以寫 const { lat: latitude } = location;。

    第四章:進階技巧

    程式開發跟人生一樣,充滿了意外。有時候你以為箱子裡有東西,打開卻是空的,解構賦值提供了一些機制來處理這些狀況。

    1. 預設值 (Default Values) —— 備案計畫

    假設你在做一個抽獎系統,有些會員資料裡有填「暱稱」,有些沒有。

    JavaScript
    
    const memberA = { id: 1, nickname: "超級瑪利歐" };
    const memberB = { id: 2 }; // 這位懶惰的會員沒填暱稱
    
    // 設定預設值
    const { nickname = "路人甲" } = memberB;
    console.log(nickname); // 印出:路人甲

    語法 { nickname = “路人甲” } 的意思是:

    1. 先去物件裡找 nickname。
    2. 如果有找到值,就用那個值。
    3. 如果是 undefined(找不到),就用 “路人甲” 當作值。

    這就像是去買便當,如果你沒說要什麼飲料,阿姨就「預設」給你養樂多,這能有效防止你的網頁因為讀不到資料而變成一片空白(或出現恐怖的 undefined)。

    2. 巢狀解構 (Nested Destructuring) —— 箱中之箱

    現實生活中的資料通常很複雜,像是「使用者的地址」可能又包含「城市」和「街道」。

    JavaScript
    
    const userProfile = {
      name: "阿呆",
      address: {
        city: "台北市",
        street: "羅斯福路",
        zip: 100
      }};

    如果你只想拿到 city,要怎麼做?

    JavaScript
    
    // 一層一層剝開洋蔥
    const { address: { city } } = userProfile;
    console.log(city); // 台北市

    這行程式碼的意思是:「去 userProfile 找 address,但不要把 address 拿出來,請進去 address 裡面再找 city,把 city 拿出來。」 所以執行完後,你會有 city 變數,但不會有 address 變數。

    第五章:實戰情境

    這可能是解構賦值在 Web 開發(特別是 React 框架)中,最最最重要的應用。

    情境:手搖杯的客製化

    想像你要寫一個函式來處理手搖杯訂單,一杯飲料可能有很多參數:甜度、冰塊、加料、尺寸、要不要袋子…

    如果不使用解構,你的函式可能會長這樣:

    JavaScript
    
    // 舊寫法:參數順序必須死記硬背
    function orderTea(teaName, sugar, ice, topping, size) {
      console.log(`你要一杯 ${teaName},${sugar},${ice}...`);
    }
    
    // 呼叫的時候很痛苦,如果不加料還要傳 null 佔位子
    orderTea("珍珠奶茶", "半糖", "少冰", null, "大杯");

    這簡直是惡夢,如果你忘記第 3 個參數是冰塊還是甜度怎麼辦?

    解構參數的優雅寫法

    現在,我們把所有選項打包成一個「物件」傳進去,並在函式接收端直接解構:

    JavaScript
    
    // 新寫法:接收一個物件,並直接解構出需要的屬性
    // 還可以順便設定預設值!
    
    function orderTea({ teaName, sugar = "全糖", ice = "去冰", topping = "無" }) {
      console.log(`訂單:${teaName}, ${sugar}, ${ice}, 加料:${topping}`);
    }
    
    // 呼叫的時候:
    // 1. 不需要管順序
    // 2. 參數清楚明瞭
    // 3. 沒寫的就會用預設值
    orderTea({ 
      teaName: "四季春", 
      ice: "微冰", 
      sugar: "無糖" 
    });

    這在現代 Web 開發中極為常見,當你看到 function Component({ title, color }) 這樣的寫法時,請記得,它其實就是把傳進來的那個大物件,當場拆解成 title 和 color 兩個變數給函式內部使用。

    第六章:那些讓你看起來很厲害的酷招式

    最後,介紹兩個大學生在寫作業或專題時,可以用來耍帥(同時也很實用)的小技巧。

    1. 變數交換 (Swapping Variables)

    在學習程式基礎(如 C 語言或 Java)時,如果要交換兩個變數的值,通常需要一個「暫存變數(temp)」,例如要交換 A 和 B 的飲料:

    1. 先把 A 倒進空杯 C。
    2. 把 B 倒進 A。
    3. 把 C 倒進 B。

    但在 JavaScript 裡,有了解構,你可以像變魔術一樣:

    JavaScript
    
    let a = "可樂";
    let b = "雪碧";
    
    // 左邊是解構,右邊是創造陣列
    // 瞬間交換!
    [a, b] = [b, a];
    
    console.log(a); // 雪碧
    console.log(b); // 可樂

    這就像是雙手交叉瞬間交換手上的東西,非常帥氣且節省程式碼。

    2. 其餘運算符 (Rest Operator)

    有時候你只想拿走便當裡的雞腿,剩下的菜你想全部打包給室友吃,這時候可以用 …(三個點,稱為 Rest Operator)。

    JavaScript
    
    const team = ["隊長", "副隊長", "隊員A", "隊員B", "隊員C"];
    const [captain, ...others] = team;
    console.log(captain); // 隊長
    console.log(others);  // ["副隊長", "隊員A", "隊員B", "隊員C"]

    這裡的 …others 意思就是:「剩下的所有東西,幫我打包成一個陣列,放進 others 變數裡」,這在處理不確定數量的資料時非常有用。

    結語:從「整理」開始的程式美學

    恭喜你!你已經學會了現代 JavaScript 中最強大的語法之一:解構賦值

    回顧一下重點:

    1. 物件解構 {}:像是在工具箱找標籤,不看順序,只看名字。
    2. 陣列解構 []:像是在自助餐排隊,只看順序,變數名字隨你取。
    3. 預設值 =:防止資料缺漏的備案。
    4. 函式參數解構:讓你的函式介面更乾淨、更好用。

    解構賦值不僅僅是為了讓程式碼變短,更重要的是讓程式碼的「意圖」變清晰。當你閱讀 const { name } = user 時,你不用看上下文就能知道:「哦,這段程式碼只關心使用者的名字。」在未來的 Web 開發學習路上,不管是 React、Vue 還是 Node.js,你將會每天、每小時都看到解構賦值的身影。它就像是程式設計師的瑞士刀,一旦用習慣了,你就再也回不去那個徒手拆包裹的舊時代了。現在,打開你的瀏覽器開發者工具(按 F12),試著解構一下你身邊的資料吧!