0920~0926_夏季暢銷第三波BN

Node.js Fullstack 原理與實務

  • 79 616
    780
  • 分類:
    中文書電腦資訊網頁開發網頁設計概論
    追蹤
    ? 追蹤分類後,您會在第一時間收到分類新品通知。
  • 作者: Jollen 追蹤 ? 追蹤作者後,您會在第一時間收到作者新書通知。
  • 出版社: 仕橙研策 追蹤 ? 追蹤出版社後,您會在第一時間收到出版社新書通知。
  • 出版日:2025/09/01

活動訊息

想找書的時候,特別想偷看網友的書櫃... 原來大家都在看這本 ↓↓↓

用閱讀開啟視野,讓書成為照亮你人生的光
【金石堂選書】本月推薦您這些好書👉 快來看看

內容簡介

◎代理經銷 白象文化

名人推薦

◎這本書是為 Node.js 初學者設計的入門教材,也是一份幫助你從零開始、逐步建立實作能力的學習指南。
每個章節都從基本觀念開始,帶你 Step-by-Step 寫出一段完整、能運作的小程式。在閱讀過程中,你會學到:

1. 如何用 Node.js 建立基本的 Web 應用程式
2. 如何用 Express.js 架構 RESTful API
3. 如何整合 HTML5 和前端框架,完成簡單的 Fullstack 架構
4. 如何用 WebSocket 和 JSON 實作即時雙向資料傳輸
5. 如何使用 MongoDB 儲存資料,並結合 Mongoose 建立資料模型

本書採用清楚的步驟式教學,並搭配語意導向的說明,幫助你了解每一段程式碼背後的設計邏輯。本書的理念,不是教你背熟語法,而是讓你具備基礎的程式設計思考力:能夠拆解問題、設計資料流程,並寫出能解決實際需求的應用程式。而是一本實務導向的 Node.js 入門教科書,跟著章節動手做,你會開始習慣查資料、讀官方文件,甚至能理解許多進階開發者的實戰經驗分享。如果你準備開始了,我們就從 console.log(“Hello World”) 開始吧。

作者

◎ Moko365 技術總監、Flowchain 基金會(新加坡)創辦人,專精於 Embedded Linux、Android Framework 與驅動程式開發,累積超過二十年研發與實務經驗。曾為 Motorola、HTC、LG、OPPO、騰訊、廣達等五十餘家企業提供技術顧問、內訓與課程設計服務,擅長系統架構設計、軟硬整合開發與研發流程管理。

2016 年創辦 Flowchain 基金會,推動以 Node.js 為核心的物聯網區塊鏈作業系統,實踐開源實作與跨域整合,並取得多項國際專利。多年來受邀於日本、加拿大、新加坡、斯洛維尼亞等地演講與授課,並多次在 Open Source Summit、OpenIoT Japan、FOSSASIA Summit 等國際會議發表技術演說。其代表性研究《Devify: Decentralized IoT Software Framework》曾於 AIoTAS’17(加拿大)發表,並收錄於 ACM SIGBED Review。

Jollen 著有十餘本技術書,涵蓋 Linux、Embedded Linux 與 PHP,具備深厚的技術書寫與教材編撰經驗。近期聚焦於 WebAssembly 與語言模型整合開發,並主筆《Node.js 與 LLM》系列教材。

Jollen's Blog:
https://jollen.org/blog
讀者服務:
www.jollen.org

目錄


第 1 章:JavaScript 設計模式
1.1 Object(物件)
1.2 宣告 Class
1.3 使用 Factory Pattern
1.4 Constructor Pattern
1.5 Design Pattern for Front-End
1.6 Module Pattern
1.7 jQuery Pattern
1.8 選擇器模式
1.9 Prototype Pattern
1.10 其它模式

第 2 章:HTML5 軟體開發的概念
2.1 HTML5 的 Runtime 是瀏覽器
2.2 從 Chrome 瀏覽器談起
2.3 Web Fullstack 軟體開發的概念
2.4 JavaScript 也能開發雲端服務
2.5 Data Push 設計模式
2.6 Device API 的革命時代
2.7 重要的資訊交換格式:JSON
2.8 結語:HTML5 是雲端技術

第 3 章:Node.js 入門 - URL Routing 篇
3.1 Hello, World
3.2 製作 Node.js 模組
3.3 URL Routing
3.4 設計 HTTP API
3.5 解析 Query String

第 4 章:Node.js 入門 - WebSocket 與 JSON 篇
4.1 第一個 WebSocket 伺服器
4.2 學習 JSON 格式
4.3 製作 WebSocket 用戶端
4.4 使用 jQuery 模式
4.5 使用 this 物件

第 5 章:軟體思惟 - Lambda 篇
5.1 Lambda
5.2 Callback Function
5.3 從 TypeScript 談 Promise
5.4 使用 Promise 封裝非同步處理流程
5.5 async/await:語意同步化
5.6 非同步 Node.js 技術演化

第 6 章:軟體思惟 - Web Service 篇
6.1 再探 HTTP API
6.2 REST
6.3 REST + JSON 範例

第 7 章:軟體思惟 - Non-blocking IO 篇
7.1 認識 Non-blocking IO
7.2 非同步式讀取多個檔案
7.3 深入 Node.js 非同步錯誤處理

第 8 章:Node.js 應用 - Express.js 入門
8.1 Express.js 初體驗
8.2 MVC 與 HTML Template Engine
8.3 解析 app.js
8.4 Express URL Routing
8.5 Middleware 的觀念

第 9 章:Express.js 應用 - Middleware
9.1 Express Middleware 控制流程
9.2 使用 app.use() 撰寫全域 Middleware
9.3 常用的 Express.js Middleware

第 10 章:REST API 架構 - 使用 Express.js
10.1 服務導向架構
10.2 關於 SOA 與 3-Tier 架構
10.3 Presenetation 在 Client 端
10.4 Express.js 與 REST API
10.5 Node.js Chat Client
10.6 WebSocket 即時推播

第 11 章:REST API 應用 - 使用 jQuery
11.1 呼叫 REST API - 使用 jQuery
11.2 從 Key-Value 對應出發:前端框架的語義演化

第 12 章:MVC 架構實作 - Backbone.js 入門
12.1 Backbone Way
12.2 認識 View.$el
12.3 認識 Backbone.Model
12.4 認識 Backbone.Model.fetch
12.5 認識 Backbone.Model.save

第 13 章:NoSQL 資料庫應用 - 使用 MongoDB
13.1 關於 MongoDB
13.2 安裝 MongoDB 資料庫伺服器
13.3 使用 Mongoose Driver:語意模型起點
13.4 CRUD 實作:語意資料的最終流轉

序/導讀

◎學習程式設程式,不只是學習語法,而是深入思考程式碼運作的情境與意義(「語境」與「語意」)。我們不只是在學習程式語言,而是在訓練思考方式:用語意與語境來建構邏輯。
Node.js 以非同步處理的語境,來實作雲端 API;Node.js 不只是「快速開發雲端 API」的工具,它更結合了 JavaScript 程式語言的藝術,以及 Fullstack 的開發思惟。
本書帶領 Node.js 初學者,從 JavaScript 程式語言,到入門 Node.js的軟體思惟與設計:
• 第 1 章,我們從 函數與設計模式啟程,理解 JavaScript 的語言本
質;
• 第 3 至 4 章,我們實作出一個能跑的 Node.js Web App,開始探索
route()、pathname 與 REST 架構;
• 第 5 章 開 始, 你 會 接 觸 非 同 步 程 式 設 計 的 世 界, 從 callback、
Promise 到 async/await——Node.js 對非步處理邏輯的封裝
• 然後進入 WebSocket、JSON、Express.js、MongoDB 等技術

語法不會讓你變強,思維才會。例如:我們不是在學寫 if/else,而是在引導:「你能不能用語言來設計一段流程?你能不能把一個情境實作出來?」

這本書的寫作宗旨,不在介紹「初學者要記住什麼語法」。對於第一次接觸程式語言的初學者來說,本書也可以做為「踏進程式設計的第一本書」。
當你看到 function() 語法時,不再只是思考怎麼寫才能執行,而是思考它「為什麼存在」;讓我們從 console.log("Hello World") 開始 Node.js 的旅程。

——Jollen

試閱

第 1 章:JavaScript 設計模式
1.1 Object(物件)
JavaScript 的第一堂課,就是理解「物件生成」這件事。而物件,不只是資料容器,更是程式語意(Semantic)行為的包裝體(物裝封裝程式碼邏輯)。
在 JavaScript 裡,我們可以使用 function 關鍵字宣告一個可重複使用的物件工廠(Object Factory),並搭配 new 來生成具備屬性與方法的物件;另一種更直接的方式,是使用 Object.create() 或「物件實字(Object Literal)」語法。
var person = {
name: "Jollen",
job: "Software Developer",

queryJob: function() {
alert(this.job);
}
};

person.queryJob();
在這段範例中:
person 是一個物件(Object)
name 和 job 是物件的屬性(attribute)
queryJob() 是一個方法(method),透過 this 取得 job 的值
這是典型物件導向語言裡的「語意」、一種觀念:資料(Data)與行為(Behavior)被包裝在同一個結構中。
1.1.1 語意(Semantic)與語境(Context)
寫程式不是在「學語法」,而是「看懂程式在說什麼」。每一段程式碼都不是「只是語法」,它有想表達的「意思」:我們稱它為語意(semantic)。例如,在 JavaScript 顯示字串的語法:
console.log('Error: not enough memory space.')
這段程式碼的「語意」是「在螢幕上顯示 Error: not enough memory space.」,它的「語境」通常會出現在程式遇到「記億體不足」的情況下,來顯示此訊息。
所以,console.log() 是一個語法(函數),它會根據不同的「語境」出現在程式碼。語意(例如:函數)會出現在哪裡、與哪些變數、資料或邏輯有關係,我們稱這些為語境(Context)。
我們常說:「會寫程式」和「懂程式」其實是兩件事。以中文為例:
今天早上天氣很好。
這句話語法沒問題,主詞、時間、謂語都正確。但如果你心裡的真正意圖是:
今天早上天氣很好(心理想:可以出門運動)
這才是語意層次的訊息。也就是說,「語法正確」只是形式,「語意清楚」才是真正的溝通。回到寫程式:寫出 class 來宣告「類別」,語法正確能執行。但你有思考它的意義嗎?
這樣的思考方式,才是真正在學「程式設計」,而不是只學「語法」運用。語法是寫給編譯器看的,語意則是寫給你(開發者)看的。語意清楚,才是說出你要表達的邏輯與設計。這就是學習程式設計的方法:語意導向學習——不是只學會語法,而是學會「思考為什麼要這樣寫」。

1.1.2 語法升級對照(ES6)
將上述範例,改用 ES6 的語法實作,可以更清楚地將資料與方法結構化,以下是等價的語法重構:
const person = {
name: "Jollen",
job: "Software Developer",

queryJob() {
alert(this.job);
}
};

person.queryJob();
差異說明
語法面向 ES5 ES6
宣告變數 var const(不可變)
方法寫法 queryJob: function() {} queryJob() {}
語意與語境 具備 this 語境,但無模組封閉 建議封裝於模組(Module Pattern)中
在第 4 章,我們將看到:物件(Object)不只是資料的容器,更是功能與語境封裝的單位。我們透過 jQuery plugin、WebSocket client,實踐了「以物件操作自身」的結構思維。
回過頭來看這個範例,會發現即便簡單如 person.queryJob(),也蘊含著物件內部語意行為(Semantic Behavior)的綁定與執行語境的切換。
關於 Node.js 的 JavaScript 語法標準,後續 3.6 節再進行詳細說明。
下一節,我們將進一步進入以 function 宣告物件行為的寫法 —— Instantiable Function。

1.2 宣告 Class
同樣地,早期 JavaScript 語言,並沒有類似 Class 這樣的語法(直到 ES6);所以,在 ES5 中,我們是以 function 關鍵字來實作所謂的「Class」,也就是 Instantiable Function,這種寫法本質上是函數宣告:
function Person(name, job) {
this.name = name;
this.job = job;
this.queryJob = function() {
alert(this.job);
};
}
將 Function 當作類別使用,代表我們也可以使用 new 關鍵字將其實例化(instantiate)成一個物件。
上述函數內部使用 this 來定義屬性與方法。當透過 new 關鍵字呼叫這個函數時,就會生成一個新的物件實例,並綁定到這個 this 上。
這裡使用到 JavaScript 的 function 語法,但它的「語意」不是為了宣告函數,而是在定義類別(class)。這個範例的語意,是在實作「物件導向」的觀念。
以下是一個完整的例子:




MokoCrush





在這個例子中,person 是 Person 類別的實例。當執行 person.queryJob() 時,瀏覽器會顯示該工作職稱。

1.2.1 語法升級對照:ES5 vs ES6
JavaScript 自 ES6 起,正式導入了 class 語法,讓語意與封裝更接近物件導向設計。



function 與 class 觀念對照
概念 ES5 語法 ES6 語法
類別宣告 function Person(...) { ... } class Person { constructor(...) }
方法定義 在 constructor 裡手動賦值 直接定義在 class 區塊內
繼承 使用 Object.create() / prototype 使用 extends
this 綁定 需手動保存 var self = this 使用箭頭函數或 class 方法
用「語意」來思考,才是真正在學寫程式,而不是用「語法」來學習寫程式。例如:思考 class 的「意思」與「意義」,而不是「這個語法在做什麼」。
下表整理 class 的語法(Syntax)與語意(Semantic):
function 與 class 語意對照
問題類型 語法式問題 語意式問題
初學者常問的問題 class 要怎麼宣告? 為什麼要用 class?什麼時候用比較合適?
技術論壇常見錯誤 constructor 括號錯了 建構邏輯與實例責任是否分離清楚?
專案設計核心思維 function vs class 哪個好? 是否需要封裝狀態?這個單元是否具備語意自洽性?
對照示例:ES6 寫法
class Person {
constructor(name, job) {
this.name = name;
this.job = job;
}

queryJob() {
alert(`${this.name}'s job is ${this.job}`);
}
}

const person = new Person("Jollen", "Software Developer");
person.queryJob();

1.2.2 進階 Class 繼承:extends / super
ES6 提供了 extends 與 super() 語法,使得繼承變得直覺可用。
以下是 Person 類別的延伸範例:
class Developer extends Person {
constructor(name, job, language) {
super(name, job); // 呼叫父類別的 constructor
this.language = language;
}

introduce() {
console.log(`Hi, I code in ${this.language}`);
}
}

const dev = new Developer("Jollen", "Software Developer", "JavaScript");
dev.queryJob(); // 繼承自 Person
dev.introduce();
這種語法結構,在第 4 章中我們可以用來封裝不同的前端元件行為(例如:WebSocketClient 的繼承擴展),並明確使用 super() 呼叫基礎行為。
this 綁定與原型鏈:從 ES5 到 ES6
在第 3 章與第 4 章的 WebSocket 程式碼裡,我們將會看到 this 綁定與封裝(Closure)帶來的實務挑戰。例如:
this 在 callback 裡會指向錯誤的上下文,因此需使用變數保存 (var self = this)
將函數封裝為 jQuery plugin 時,需將 this 綁定為 DOM 節點,以強化封閉性
這些問題,在 ES6 的 class 與箭頭函數下得以改善:箭頭函數不會綁定自己的 this,會自動指向外層作用域的 this。
本書策略說明:從 ES5 出發,導向 ES6 應用
為了幫助初學者理解 JavaScript 的語意結構與執行脈絡,本書前幾章範例皆採用 ES5 語法做為起點,逐步導入:
模組化(require vs export)
物件導向建構(constructor pattern)
callback / closure 思維
從第 4 章後期開始,將同步提供 ES6 改寫版本,並逐步導入:
class 語法
const / let 替代 var
箭頭函數(Arrow Functions)
模組語法(import / export)
這種階段式過渡的寫作策略,目的在於:讓讀者先理解 JavaScript 的底層語意,再逐步適應新語法帶來的簡潔與強大。
JavaScript 裡生成物件的做法:
使用 var(或 let, const)宣告物件
Instantiable Function(ES5)
class 語法(ES6)

1.3 使用 Factory Pattern
Instantiable Function 可使用 new 關鍵字建立物件,進一步可透過封裝的方式將物件生成過程抽象化。這就是 Factory Pattern 的用途。
Factory Pattern 是一種常見的物件生成設計模式,它在軟體工程領域中用於將物件的建立過程進行封裝抽象化。例如,以下我們將先前的範例改寫成 factory pattern 的實作:
// 不可做為 Constructor Pattern
function personFactory(name, job) {
const o = {};

o.name = name;
o.job = job;
o.queryJob = () => {
alert(`${name}'s job is ${job}`);
};

return o;
}

const person1 = personFactory("Jollen", "Software Developer");
const person2 = personFactory("Paul", "Product Manager");

person2.queryJob();
範例中,person1 和 person2 的物件生成過程被抽象化(封裝)起來。在主程式內,我們看不到 new 關鍵字的使用,而是透過 personFactory() 函數來封裝物件的生成。然而,使用 factory pattern 的缺點在於無法判斷物件原本的 class type,例如:
1 alert(person1 instanceof Object); // true
使用 personFactory() 建立的物件實際上是 Object 的實例。如果需要明確生成 Person 類別的物件,仍建議使用先前介紹的 constructor 模式:
// 可做為 Constructor Pattern
function Person(name, job) {
this.name = name;
this.job = job;
this.queryJob = function() {
alert(this.job);
};
}

// 將 Person() 視為 constructor
const person = new Person("Jollen", "Software Developer");

alert(person instanceof Person); // true
在這個範例中,物件 person 確實為 Person 類別的實例。將函數 Person() 視為 constructor,而非一般函數,能在概念上達到明確判斷 class type 的目的。

1.3.1 Factory Pattern 的優點與限制
使用 Factory Pattern 建立物件時,有以下的優點與限制:
優點:
提高物件建立邏輯的封裝性與可重用性
能彈性地建立不同結構的物件,適合動態決定物件屬性的情境
避免程式碼過度依賴具體的建構函數,提升系統的擴充性與維護性
限制:
生成的物件無法透過 instanceof 判斷原始類型
建立物件的方式較為隱晦,可能增加程式碼閱讀的困難度
實務範例:動態物件生成
以下提供一個更具實務價值的範例,展示 Factory Pattern 如何動態生成不同屬性的物件:
// 動態決定生成物件屬性
function employeeFactory(type, name) {
const employee = { name };

if (type === 'Developer') {
employee.job = 'Software Developer';
employee.queryJob = () => alert(`${name} writes code.`);
} else if (type === 'Manager') {
employee.job = 'Product Manager';
employee.queryJob = () => alert(`${name} manages products.`);
} else {
employee.job = 'Unknown';
employee.queryJob = () => alert(`Unknown role for ${name}.`);
}

return employee;
}

const emp1 = employeeFactory('Developer', 'Alice');
const emp2 = employeeFactory('Manager', 'Bob');

emp1.queryJob(); // Alice writes code.
emp2.queryJob(); // Bob manages products.
此範例清楚說明 Factory Pattern 如何透過動態條件,建立具不同屬性與行為的物件,有效提升程式設計上的彈性與抽象化能力。
1.4 Constructor Pattern
以上的觀念,可以用一句話來總結:
函數(functions)就是物件(objects)
這是 JavaScript 極為關鍵的語言設計特性,尤其在實務開發中,廣泛應用於 callback function、事件綁定與 constructor function 的建立。
在前一節的範例中,我們將 Person() 當作 constructor 來使用,這種設計模式即為 Constructor Pattern。它透過 new 關鍵字配合函數語法,實現物件的初始化與封裝,具有高度可讀性與擴充性。
上述兩個範例中,只有第二個(使用 new Person() 的寫法)才符合 Constructor Pattern 的語意。其具備以下三個語法特徵:
不需要手動產生物件(不使用 new Object())
直接使用 this 關鍵字指定屬性與方法
函數內不需要明確 return 物件
此外,依循物件導向的慣例,constructor 的命名建議使用大寫字母開頭(如 Person),以區分與一般函數的用途。
以下為範例:
// Constructor Pattern 範例
function Person(name, job) {
this.name = name;
this.job = job;
this.queryJob = function() {
alert(`${this.name}'s job is ${this.job}`);
};
}

const person1 = new Person("Jollen", "Software Developer");
const person2 = new Person("Paul", "Product Manager");

person2.queryJob();
1.4.1 為什麼 Constructor Pattern 更接近類別語意?
使用 new 關鍵字時,JavaScript 會隱式執行以下操作:
1.建立一個新的空物件 {}
2.將 this 綁定到該新物件
3.將函數內的屬性與方法掛載到該物件上
4.回傳這個物件(即便沒有寫 return)
這一連串語意行為,使得 Constructor Pattern 成為模擬「類別初始化」的典型方式,亦是 JavaScript 進入以類別為基礎結構的起點。
延伸補充:ES6 class 的語法轉譯
ES6 提供了 class 語法糖1,其實本質上仍是 Constructor Pattern 的語法包裝。例如:
class Person {
constructor(name, job) {
this.name = name;
this.job = job;
}

queryJob() {
alert(`${this.name}'s job is ${this.job}`);
}
}

const person = new Person("Alice", "Engineer");
person.queryJob();
雖然語法看似「類別」,但在語意上仍是基於原型鏈的 Constructor 機制。

1.4.2 深入比較:Factory Pattern vs Constructor Pattern
Factory Pattern 與 Constructor Pattern 差異對照
面向 Factory Pattern Constructor Pattern
是否使用 new 否 是
類型判斷支援 instanceof 無法判斷自定類別 可使用 instanceof 判斷類別
建立過程封裝彈性 高,適合動態條件分支 中,較為明確但缺乏動態決策能力
原型鏈(Prototype)支援 否,無法共享方法 是,可透過 prototype 節省記憶體
記憶體效能 每個實例各自擁有方法拷貝(高成本) 可透過 prototype 共用方法(低成本)
技術建議:何時選用 Constructor?
當需要建立明確的類別型別與結構時
當需搭配原型鏈設計與方法共享機制(如多人共用 queryJob() 方法)
當希望能明確辨識物件來源(如 instanceof Person)
反之,若建立的是靜態物件、一次性使用或需高度客製化屬性時,可考慮採用 Factory Pattern。
進一步延伸:使用 prototype 擴充共用方法
在 constructor 函數中,每建立一個新物件,其方法會被重複配置一次,造成記憶體的浪費。透過 prototype,我們可以將方法掛載到原型鏈上,讓所有實例共用同一份方法邏輯。
function Person(name, job) {
this.name = name;
this.job = job;
}

Person.prototype.queryJob = function() {
alert(`${this.name}'s job is ${this.job}`);
};

const person1 = new Person("Jollen", "Software Developer");
const person2 = new Person("Paul", "Product Manager");

person1.queryJob();
person2.queryJob();
此方式能有效節省記憶體資源,並保持邏輯一致性。

1.4.3 原型鏈上的繼承:模擬類別繼承的機制
JavaScript 並非傳統類別導向語言,但可透過原型鏈實現繼承行為。以下示範 Employee 繼承 Person 的範例:
function Person(name) {
this.name = name;
}

Person.prototype.sayHello = function() {
alert(`Hi, I'm ${this.name}`);
};

function Employee(name, job) {
Person.call(this, name); // 繼承屬性
this.job = job;
}

Employee.prototype = Object.create(Person.prototype); // 繼承方法
Employee.prototype.constructor = Employee;

Employee.prototype.describeJob = function() {
alert(`${this.name} is a ${this.job}`);
};

const emp = new Employee("Alice", "Engineer");
emp.sayHello(); // 繼承自 Person
emp.describeJob(); // 定義於 Employee
透過 Object.create() 可建立新的原型物件,實現方法繼承。另外,Object.create() 建立的物件,不具備 constructor 語義(即沒有物件導向的 contructor 函數);因此,此方式適合作為原型鏈用途,而非初始化語義。
後續可使用 ES6 語法,再重新指定 constructor 以保留類別型別(Class Type)的正確性。

1.5 Design Pattern for Front-End
用白話文來說,「設計模式」就是撰寫程式碼與解決重複問題的一種固定方法。它不是語法,也不是 API,而是一種經過驗證的「思維模板」。在前端開發的領域裡,設計模式扮演著極為關鍵的角色。
隨著 HTML5 與 JavaScript 的普及,開發者在構建大型、模組化的應用時,必須面對複雜的結構與維護成本。這時候,設計模式就不再是選修,而是必修。
在 HTML5+JavaScript 世界中,最核心的兩個設計模式分別是:
模組模式(Module Pattern)
jQuery 插件模式(jQuery Plugin Pattern)
這兩者不僅是「程式碼風格」,更是建構大型前端應用的骨架與規範。沒有這些模式,再多的語法技巧都無法撐起一個穩健可維護的系統。
為什麼語法不夠?
要強調一個觀念:只會 JavaScript 語法,是無法寫出高品質前端程式的。會寫 for、if、function,就像會用鋸子跟釘子,還不等於蓋得出一棟好房子。
設計模式正是這些「建築藍圖」,幫助你把語法組合成有結構、有彈性、可維護的工程作品。
這也就是為什麼我們說:
JavaScript 的設計模式,才是從語法到架構的關鍵橋梁。

1.5.1 現代前端框架仍以設計模式為根基
即便你日後進入 React、Vue、Svelte 等框架世界,你仍會發現這些框架背後的元件設計、狀態管理、事件機制,本質上仍建立在幾種核心設計模式之上,例如:
Module Pattern:對應 ES6 modules、Vue 的單檔元件
Observer Pattern:對應 React 的 useEffect、Redux 的訂閱機制
Composite Pattern:React 元件樹的合成模型
Strategy Pattern:狀態管理中的行為切換策略(如 reducer function)
學會這些設計模式,不只是為了寫 jQuery,更是為了理解框架背後的設計哲學與工程抽象。

1.6 Module Pattern
如同此設計模式的名字所述,Module Pattern 的目的是將程式碼「模組化」;在 JavaScript 中進行模組化,有其固定做法。模組化的前提,是使用 Closure(封閉性)來建立私有作用域。
接下來,我們將以連續的範例來說明 Module Pattern。在繼續進行之前,請務必熟悉 JavaScript 的物件與作用域觀念。

1.6.1 使用 Private/Public 觀念
請不要再使用 Local variable 與 Global variable 的寫法,這在 HTML5+JavaScript 的開發實務中是無法維持良好架構的。以下為一個典型的錯誤範例:
// [ES5]
var count = 0; // GLOBAL

function incrementCounter() {
count++; // GLOBAL
return count;
}

function resetCounter() {
var orig; // LOCAL
orig = count;
count = 0;
}
這個範例只是用來說明 Local 變數與 Global 變數的基本寫法。我們現在要更進一步,將 Local variable 重構為 Private attribute,而 Global variable 則重構為 Public attribute。如下:
// [ES5]
var testModule = (function () {
var counter = 0; // Private

return {
incrementCounter: function () {
return ++counter;
},
resetCounter: function () {
counter = 0;
}
};
})();
對照寫法:ES6 模組化
// [ES6]
const testModule = (() => {
let counter = 0;

const incrementCounter = () => ++counter;
const resetCounter = () => {
counter = 0;
};

return {
incrementCounter,
resetCounter
};
})();
對照分析:
改寫 var 為 let/const:明確區分可變與不可變。
改寫 function 為 arrow function:簡潔語法,保留語意一致性。
ES6 物件回傳值寫法:在 return 中直接回傳物作(key/value paris)。
閉包:定義語意範圍(Scope)
這段程式碼的重點是:原本使用 function 關鍵字定義的結構,現在被更進一步包裹為一個 module,形成封閉的範圍,該 module 就叫做「閉包」。此時,區域變數 counter 成為 Private attribute,而兩個函式則作為模組的 Public method。
JavaScript 的語意範圍(Scope),指的是變數可以被存取到的範圍。例如:函數範圍(Function Scope)-在函數內部宣告的變數,只能在該函數內部被存取,函數外的程式碼無法存取該變數。
將這段程式碼封裝為 JavaScript module,就是 Module Pattern 的核心精神。Closure 的目的,是為了避免全域變數污染;一個全域變數可能會被其他程式碼任意修改,而將它封閉在 module 裡,則只有模組內部能夠存取與操作。
外部程式碼無法修改封閉程式碼內的變數。從觀念上來看,透過 module 將 attribute 與 method 進行封裝,就是 closure 的應用(即 Closure 的語意)。被封裝為 JavaScript module 的程式碼,即稱為「閉包」。
簡單來說,將封閉的程式碼放進 testModule 變數裡,使 testModule 成為一個可重複使用的模組。JavaScript 沒有明確的物件導向語法,因此這些封裝技巧更多是一種「觀念上的封裝」,而非語法上的強制限制。
軟體工程常常處理的是這類抽象與結構性的思考問題,技術只是這其中的一環。我們要將軟體開發視為一種創作過程,而非僅僅是寫程式的過程。

1.6.2 Import Modules
jQuery 是一套功能強大的函式庫,它本身也是一個 module。由於 jQuery 的擴充能力極強,市面上有眾多為其打造的 plugins,因此 jQuery 不僅是函式庫,更像是一個平台,甚至是一個框架(Framework)。
在 Web 開發中,jQuery 幾乎無所不在,因此也有了一套專屬的 jQuery Pattern(後續章節將介紹)。
以下是一個以 jQuery 為參數匯入模組的範例:
// [ES5]
var testModule = (function (jQ) {
var counter = 0;

function showHTML() {
jQ(".header").html("

" + counter + "

");
}

return {
incrementCounter: function () {
return ++counter;
},
resetCounter: function () {
counter = 0;
},
setCount: function (val) {
counter = val;
},
showCount: function () {
showHTML();
}
};
})($);
ES6 重構版本
// [ES6]
const testModule = ((jQ) => {
let counter = 0;

const showHTML = () => {
jQ(".header").html(`

${counter}

`);
};

return {
incrementCounter: () => ++counter,
resetCounter: () => { counter = 0; },
setCount: val => { counter = val; },
showCount: () => showHTML()
};
})($);
這種設計方式有兩個優勢: - 將依賴(如 $)作為參數傳入,達到依賴注入的目的,降低耦合度。 - 將所有方法封裝於閉包中,只暴露需要的操作邏輯,強化模組封裝性。

1.7 jQuery Pattern
在軟體工程領域裡,jQuery 創造了一個獨特的觀念:知名的 “$”(Dollar sign),也就是「Selector」。
而 jQuery Pattern 指的是撰寫 jQuery 插件(plugin)的一種標準設計方式。雖然技術上它看起來只是語法包裝,但在軟體工程觀點中,它代表了一種「可擴充平台」的設計哲學。
其核心概念是:
將功能封裝為模組
將模組掛載到 $ 的原型鏈上(即 $.fn)
使用者得以透過直覺的鏈式呼叫來使用擴充功能
例如,這是最常見的 jQuery pattern 用法:
$("div#news").html("

News Today

");
這行語法背後的哲學是:將 HTML DOM 的操作,封裝成簡潔的 API,讓程式碼結構更具可讀性與表達性。
1.7.1 模組化 + 插件註冊 = jQuery Pattern
假設我們希望透過 WebSocket 與伺服器互動,並將訊息即時顯示在某個 div 上,我們可以:
1.建立一個 WebSocket 功能模組
2.將它以插件方式掛載至 jQuery
3.使用 $().createWebSocket() 來啟用該功能
Plugin 設計範例(ES5 版本)
(function($) {
$.fn.createWebSocket = function () {
if ("WebSocket" in window) {
alert("WebSocket is supported by your Browser!");
var ws = new WebSocket("ws://:8888/start");

ws.onopen = function () {
// 連線開啟
};

ws.onmessage = function (evt) {
// 收到訊息
};

ws.onclose = function () {
// 關閉連線
};

ws.onerror = function () {
// 發生錯誤
};
} else {
alert("WebSocket NOT supported by your Browser!");
}
};
})($);
ES6 重構寫法
(($) => {
$.fn.createWebSocket = function () {
if ('WebSocket' in window) {
alert('WebSocket is supported by your Browser!');
const ws = new WebSocket(`ws://localhost:8888/start`);

ws.onopen = () => console.log('WebSocket opened');
ws.onmessage = (evt) => {
console.log(`Received: ${evt.data}`);
this.html(`

${evt.data}

`);
};
ws.onclose = () => console.log('WebSocket closed');
ws.onerror = (err) => console.error('WebSocket error:', err);
} else {
alert('WebSocket NOT supported by your Browser!');
}
};
})(jQuery);
差異說明表
jQuery Plugin 範例重構重點
差異點 ES5 寫法 ES6 重構 說明
變數宣告 var const 明確不可變語意
函式 function arrow function 保留 this,語法簡潔
字串操作 拼接字串 template literal 可讀性提升


1.7.2 插件開發規則與範式
良好的 jQuery 插件,應該滿足以下條件:
支援 鏈式操作(return this)
支援 多元素處理(透過 this.each())
可設定預設參數與使用者覆寫(使用 $.extend())
範例:帶參數的簡易插件
$.fn.sayHi = function (options) {
const settings = $.extend({
message: 'Hi there!'
}, options);

return this.each(function () {
$(this).text(settings.message);
});
};
呼叫方式:
$('div.welcome').sayHi({ message: 'Hello, world!' });

1.7.3 與現代框架設計的連結
jQuery pattern 不只是語法技巧,更啟發了許多現代框架設計中的「擴充點」概念:
如何擴充擴架
jQuery Pattern 概念 現代框架中的對應 範例
Plugin 封裝 Vue component、React hook useWebSocket()
鏈式操作 RxJS、Lodash FP pipe()、chain()
原型擴充 Vue.directive、Class.prototype Vue.directive()
jQuery Plugin Pattern 是 JavaScript 生態系中第一批真正「框架化」的設計行為。它不只是方便使用,更是一種工程封裝邏輯的啟蒙。

配送方式

  • 台灣
    • 國內宅配:本島、離島
    • 到店取貨:
      金石堂門市 不限金額免運費
      7-11便利商店 ok便利商店 萊爾富便利商店 全家便利商店
  • 海外
    • 國際快遞:全球
    • 港澳店取:
      ok便利商店 順豐 7-11便利商店

詳細資料

詳細資料

    • 語言
    • 中文繁體
    • 裝訂
    • 紙本平裝
    • ISBN
    • 9786269983322
    • 分級
    • 普通級
    • 頁數
    • 342
    • 商品規格
    • 23*17*1.8
    • 出版地
    • 台灣
    • 適讀年齡
    • 全齡適讀
    • 注音
    • 級別

商品評價

訂購/退換貨須知

加入金石堂 LINE 官方帳號『完成綁定』,隨時掌握出貨動態:

加入金石堂LINE官方帳號『完成綁定』,隨時掌握出貨動態
金石堂LINE官方帳號綁定教學

提醒您!!
金石堂及銀行均不會請您操作ATM! 如接獲電話要求您前往ATM提款機,請不要聽從指示,以免受騙上當!

退換貨須知:

**提醒您,鑑賞期不等於試用期,退回商品須為全新狀態**

  • 依據「消費者保護法」第19條及行政院消費者保護處公告之「通訊交易解除權合理例外情事適用準則」,以下商品購買後,除商品本身有瑕疵外,將不提供7天的猶豫期:
    1. 易於腐敗、保存期限較短或解約時即將逾期。(如:生鮮食品)
    2. 依消費者要求所為之客製化給付。(客製化商品)
    3. 報紙、期刊或雜誌。(含MOOK、外文雜誌)
    4. 經消費者拆封之影音商品或電腦軟體。
    5. 非以有形媒介提供之數位內容或一經提供即為完成之線上服務,經消費者事先同意始提供。(如:電子書、電子雜誌、下載版軟體、虛擬商品…等)
    6. 已拆封之個人衛生用品。(如:內衣褲、刮鬍刀、除毛刀…等)
  • 若非上列種類商品,均享有到貨7天的猶豫期(含例假日)。
  • 辦理退換貨時,商品(組合商品恕無法接受單獨退貨)必須是您收到商品時的原始狀態(包含商品本體、配件、贈品、保證書、所有附隨資料文件及原廠內外包裝…等),請勿直接使用原廠包裝寄送,或於原廠包裝上黏貼紙張或書寫文字。
  • 退回商品若無法回復原狀,將請您負擔回復原狀所需費用,嚴重時將影響您的退貨權益。
※ 網友掛保證,絕不踩雷書單如下 ↓↓↓
預計 2025/09/26 出貨 購買後進貨 
金石堂門市 全家便利商店 ok便利商店 萊爾富便利商店 7-11便利商店
World wide
活動ing