商用網站架設實務

LESSON-15 · 零基礎學生教材

JavaScript 基礎:陣列、物件與資料整理

完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。

先理解:這堂課解決什麼問題?

商家不只一項服務,資料若散落在多個變數中,新增方案與篩選都會變得困難。

本堂要完成:完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。

學習邊界:先完成「用陣列物件整理服務資料並產生可用結果」,不提前引入尚未教過的框架或建置工具。

先備知識與操作環境

本堂先備:不要求先會陣列物件;只要知道如何用編輯器儲存檔案、用瀏覽器開啟 files/index.html、按按鈕,並在 DevTools Console 讀取值。先用 examples/minimal.html 觀察三筆資料,再開始 Starter

  1. 檔案位置:先找到 starter/files/main.js、services 陣列、service 物件map/filter,再從本頁的最小實驗開始。
  2. 瀏覽器:開啟最小實驗與階段頁;每次修改後儲存並重新整理。
  3. DevTools:依本堂內容使用 Elements、Styles、Computed、Console 或 Network,記下第一個可觀察證據。
  4. 操作習慣:每次只修改一個檔案或一個責任,先預測、再操作、最後驗收。

先做最小實驗:先看見結果

這不是期末網站,而是一個可以直接看到本堂核心結果的最小實驗。先完成一次操作,再回到檔案和名詞卡對照。

開啟本堂最小實驗

  1. 入口:開啟 examples/minimal.html
  2. 操作:開啟 examples/minimal.html,先預測三筆資料與兩筆推薦資料,再按「整理服務資料」;比較畫面、Console 的 services/names/featuredServices,最後按「重設」。
  3. 預期:按整理後看到三筆全部服務、兩筆推薦服務,#status 顯示「共 3 項服務,推薦 2 項」,Console 展開三個資料結果;按重設後清單清空且狀態回到「尚未整理」。
  4. 重設:按「重設」回到初始狀態,或重新整理 examples/minimal.html;這份示範頁只讀,不要直接修改。

學生練習流程

依序完成每一張卡;目前只聚焦一個步驟,先操作,再用可觀察證據確認結果。

  1. 1

    最小實驗

    先開啟 examples/minimal.html,按「整理服務資料」與「重設」,記下畫面、Console 與 Elements 各自提供的證據。
  2. 2

    名詞

    回到名詞卡,依序說出 value/type、array、object、property、index、length;先用 services[0].name 讀一筆資料,不急著寫 map。
  3. 3

    Starter

    把 Starter 複製到自己的工作資料夾,先完成三筆物件資料,再完成 names 的 map;每一步只修改 main.js 的一個區塊,按按鈕並重新整理驗收。
  4. 4

    Checkpoint

    前往 Checkpoint,先按整理看見推薦數量不正確,再只修正 main.js 的 CHECKPOINT-1;確認 filter 的 predicate 使用 service.featured === true
  5. 5

    Solution

    前往 Solution,逐檔對照資料宣告、map、filter、renderResult 與重設流程;用 Console 展開 services、names、featuredServices,確認原始 services 仍是三筆。
  6. 6

    變體驗收

    完成價格區間變體與獨立挑戰,留下資料形狀、操作前後、畫面/Console/Elements 證據;本堂不加入 fetch、API、框架或完整服務卡元件,下一堂再接 DOM 渲染。

檔案地圖:每個位置負責什麼?

先不要急著背檔名;請把檔案位置和責任連起來。你在階段頁會看到同一份檔案的可執行版本。

先學會這些詞

先從名詞、英文與白話意思開始;每次只展開一張名詞卡,再對照正式定義、範例與驗收證據。專業術語語法檔案路徑會使用不同樣式。第一次遇到術語時,先回到這裡,不要靠猜。

本堂 16 個詞先選一組,再展開需要的名詞卡;每次只保留目前的學習焦點。

資料與型別

6 個詞
value 白話意思:程式目前拿來使用的一份資料,例如文字、數字或 true/false。 展開查看正式定義、範例與驗收證據
正式定義
JavaScript 運算式計算出的資料,可以被指定給變數、傳給函式或放進物件
什麼時候用
讀程式碼時先問「這裡拿到的是什麼資料?」。
最小範例
1200 是一個數字值,"到府諮詢" 是一個文字值。
可觀察證據
Console 直接印出值,並可搭配 typeof 觀察型別
容易混淆
變數混淆;變數是名稱,值是名稱目前指向的資料。
型別type 白話意思:描述一個值屬於哪一種資料。 展開查看正式定義、範例與驗收證據
正式定義
JavaScript 用來區分文字、數字、布林值物件等資料種類的分類。
什麼時候用
資料結果怪怪的,或要確認數字是不是被寫成文字時。
最小範例
typeof 1200 會得到 "number",typeof "1200" 會得到 "string"。
可觀察證據
Console 顯示 typeof 的結果與原始值。
容易混淆
property 混淆;型別描述資料種類,property物件裡的欄位名稱。
變數variable 白話意思:一個可以用名稱找到資料的記號。 展開查看正式定義、範例與驗收證據
正式定義
由識別名稱綁定、可在程式中讀取其值的宣告。
什麼時候用
需要在多個步驟重複使用同一份資料時。
最小範例
const services = []; 中 services 是變數名稱。
可觀察證據
Console 輸入 services 可以展開目前資料。
容易混淆
和常數混淆;const 不能重新指定變數本身,但裡面的物件資料仍可能被修改。
原始資料original data 白話意思:最初建立、後面步驟拿來整理的資料。 展開查看正式定義、範例與驗收證據
正式定義
在資料轉換流程中作為來源、應保持責任清楚的輸入集合。
什麼時候用
要比較 mapfilter 前後結果,或避免後續步驟改壞來源時。
最小範例
map 與 filter 後仍可用 services 展開三筆原始物件。
可觀察證據
比較 services.length、欄位與前後快照,而不是只看新陣列
容易混淆
和新結果陣列混淆;names 與 featuredServices 是推導結果,不取代 services。
布林值boolean 白話意思:只有 true 或 false 的資料。 展開查看正式定義、範例與驗收證據
正式定義
代表二元真偽狀態的 JavaScript 原始資料型別
什麼時候用
要表示推薦與否、是否啟用或條件是否成立時。
最小範例
featured: true;service.featured === true 的結果也是布林值。
可觀察證據
Console 顯示 true/false,不能把 "true" 文字當成同一種值。
容易混淆
和文字混淆;true 沒有引號,"true" 是字串。
嚴格相等strict equality (===) 白話意思:同時確認值和型別都相同的比較方式。 展開查看正式定義、範例與驗收證據
正式定義
以 === 比較兩側資料,只有值與型別都相同才回傳 true。
什麼時候用
filter 條件要明確判斷 featured 真的是布林 true 時。
最小範例
service.featured === true 不會把文字 "true" 當成布林 true。
可觀察證據
Console 比較 true、"true" 與 1 的結果。
容易混淆
和 = 賦值混淆;=== 是比較,= 是把右側資料指定給左側。

陣列與物件

5 個詞
陣列array 白話意思:依順序放多筆資料的清單。 展開查看正式定義、範例與驗收證據
正式定義
具有索引順序與 length 屬性JavaScript 集合型資料。
什麼時候用
有多筆服務、商品、文章或選項時。
最小範例
services = [{ name: "到府諮詢" }, { name: "定期維護" }]。
可觀察證據
Console 展開陣列、讀取 length 與第 0 筆資料。
容易混淆
物件混淆;陣列重點是多筆有順序的資料,物件重點是欄位名稱與值。
物件object 白話意思:用欄位名稱描述一筆資料。 展開查看正式定義、範例與驗收證據
正式定義
property name 與 value 組成、可表達一個實體資料形狀的 JavaScript 值。
什麼時候用
一筆服務同時需要名稱、價格與推薦狀態時。
最小範例
{ name: "到府諮詢", price: 1200, featured: true }。
可觀察證據
Console 展開物件,核對每個 property 的名稱與值。
容易混淆
和 JSON 文字混淆;這裡先使用 JavaScript 物件,不討論字串轉換格式。
屬性property 白話意思:物件裡描述資料的欄位名稱。 展開查看正式定義、範例與驗收證據
正式定義
物件上可由 key 存取的資料成員;本堂使用點記法讀取。
什麼時候用
需要取得 service 的 name、price 或 featured 時。
最小範例
service.name 讀取目前這筆服務的 name property。
可觀察證據
Console 印出 service.name,並與物件展開內容逐字比對。
容易混淆
index 混淆;property 用名稱找欄位,index 用位置找陣列項目。
索引index 白話意思:陣列中每一筆資料的位置編號,從 0 開始。 展開查看正式定義、範例與驗收證據
正式定義
用非負整數定位陣列項目的數值位置;第一筆是 index 0。
什麼時候用
只想觀察第一筆資料,或需要說明順序時。
最小範例
services[0] 取得第一筆服務,services[1] 取得第二筆。
可觀察證據
Console 展開 services[0],確認它是到府諮詢。
容易混淆
property 混淆;services[0] 是位置,services[0].name 才是欄位。
長度length 白話意思:陣列目前有幾筆資料。 展開查看正式定義、範例與驗收證據
正式定義
陣列提供、代表元素數量的唯讀數值屬性
什麼時候用
要確認資料筆數、迴圈範圍或驗收結果時。
最小範例
services.length === 3 表示目前有三筆服務。
可觀察證據
Consolelength 與畫面顯示的資料筆數一致。
容易混淆
和最後一個 index 混淆;三筆資料的 length 是 3,最後 index 是 2。

資料處理與輸出

5 個詞
mapArray.prototype.map() 白話意思:把每一筆資料轉成另一種結果,回傳一個新陣列 展開查看正式定義、範例與驗收證據
正式定義
依序呼叫 callback,將每次回傳值組成新陣列,原陣列不因 map 自動改變。
什麼時候用
每筆資料都要產生對應結果,且輸出筆數通常和輸入相同時。
最小範例
const names = services.map((service) => service.name);
可觀察證據
names 是新陣列長度和 services 相同,而且每項是文字。
容易混淆
filter 混淆;map 轉換每一筆,filter 保留符合條件的項目。
回呼函式callback function 白話意思:交給 mapfilter,讓它在處理每一筆資料時呼叫的函式。 展開查看正式定義、範例與驗收證據
正式定義
作為參數傳入另一個函式,由接收方在指定時機執行的函式。
什麼時候用
看到 map((service) => ...) 或 filter((service) => ...) 時。
最小範例
(service) => service.name 是 map 用來處理每筆服務的 callback。
可觀察證據
在 callback 裡加 console.log,觀察它被呼叫的次數與收到的資料。
容易混淆
和一般函式呼叫混淆;callback 先被交出去,何時執行由 mapfilter 決定。
filterArray.prototype.filter() 白話意思:陣列留下符合條件的資料,回傳一個新陣列 展開查看正式定義、範例與驗收證據
正式定義
依序呼叫 callback,保留 callback 回傳 truthy 的元素並組成新陣列
什麼時候用
要找出推薦、低於預算或符合狀態的服務時。
最小範例
const featuredServices = services.filter((service) => service.featured === true);
可觀察證據
featuredServices 只包含 featured 為 true 的物件,services 仍保留三筆。
容易混淆
map 混淆;filter 不把物件轉成名稱,而是決定哪些項目留下。
條件函式predicate 白話意思:回答「這一筆要不要留下?」的函式。 展開查看正式定義、範例與驗收證據
正式定義
通常回傳布林值、用來判定元素是否符合條件的函式。
什麼時候用
使用 filter 時,需要把保留規則說清楚時。
最小範例
service.featured === true 是 filter predicate 的判斷結果。
可觀察證據
逐筆觀察 predicate 的 true/false,最後對照 featuredServices。
容易混淆
和結果陣列混淆;predicate 是判斷規則,filter 結果才是留下的資料。
DOMDocument Object Model 白話意思:瀏覽器把 HTML 變成 JavaScript 可以找到的頁面樹。 展開查看正式定義、範例與驗收證據
正式定義
代表目前文件節點與階層的程式介面;本堂只用它提供結果觀察位置。
什麼時候用
需要把本堂資料筆數與清單結果放到畫面上時。
最小範例
document.querySelector("#status") 找到狀態文字元素。
可觀察證據
Elements 的 #status、#service-list 與 #featured-list 文字和 Console 資料一致。
容易混淆
和本堂核心資料處理混淆;本堂先學資料整理,完整卡片渲染留到下一堂。

最小例子:先看懂,再複製

這段只保留本堂第一個微成果。先預測結果,再逐行讀;完整檔案請開啟下方最小實驗。

const services = [
  { name: "到府諮詢", price: 1200, featured: true },
  { name: "定期維護", price: 800, featured: false },
  { name: "安心檢查", price: 600, featured: true },
];

Live Lab:逐段讀碼與驗證

每一步只回答五件事:為什麼做、改哪裡、會看到什麼、用什麼證據確認、卡住先查什麼。

  1. Step 1

    先固定每一筆資料的形狀

    目的
    先讓學生看懂陣列裡放的是物件,而不是一長段文字;後續每一步都依同一組 property 工作。
    修改位置
    starter/files/main.js 的 services array
    建立三筆都含 name、price、featured 的服務物件
    預期結果
    Console 展開 services 看到三筆物件;services.length 是 3,第一筆的 name 是「到府諮詢」。
    驗收證據
    Console 的 services.length、services[0] 與 services[0].price。
    卡住先查
    只看 services 的第一個物件,逐字比對 name、price、featured 三個 property
  2. Step 2

    indexproperty 讀一筆資料

    目的
    把「位置」和「欄位」分開,避免把 services[0]、services[0].name 當成同一個概念。
    修改位置
    starter/files/main.js 的 services array
    Console 觀察 services[0]、services[0].name 與 services.length
    預期結果
    第一行是第一筆物件,第二行是服務名稱文字,第三行是 3;學生能說出 index 從 0 開始。
    驗收證據
    Console 三行輸出和陣列展開內容逐一對照。
    卡住先查
    先只輸入 services[0],再加上 .name;不要同時改動資料宣告。
  3. Step 3

    map 產生名稱新陣列

    目的
    理解 map 的工作是逐筆轉換,結果會是新的陣列,不能和 filter 的保留條件混在一起。
    修改位置
    starter/files/main.jsmap result
    map callback 回傳每筆 service.name。
    預期結果
    Console 顯示 ["到府諮詢", "定期維護", "安心檢查"];names 有三項,services 仍保留 price 與 featured。
    驗收證據
    Console 的 names.length === services.length,以及原始 services 仍可展開。
    卡住先查
    只讀 callback 的最後一段,確認它回傳 service.name,而不是整個 service。
  4. Step 4

    filter 與明確 predicate 找推薦服務

    目的
    讓學生把「轉換」和「挑選」拆開,並看懂 === true 是比較不是賦值。
    修改位置
    checkpoint/files/main.jsfilter predicate
    用 service.featured === true 產生 featuredServices,不覆蓋 services。
    預期結果
    featuredServices 只包含到府諮詢與安心檢查兩筆;services.length 仍是 3。
    驗收證據
    Console 展開 featuredServices、確認兩筆的 featured 都是 true,並再次觀察 services。
    卡住先查
    只檢查 filter callback 回傳的條件是否為 service.featured === true。
  5. Step 5

    把資料結果接到可觀察的畫面

    目的
    用最少的 DOM 支援讓學生看見資料處理結果;本堂重點仍是資料,不延伸完整卡片元件。
    修改位置
    starter/files/index.html 的 #status、#service-list、#featured-list 與 main.js 的 renderResult
    點擊整理按鈕後,以資料長度更新 status,並以清單顯示全部與推薦服務。
    預期結果
    畫面顯示三筆全部服務、兩筆推薦服務,狀態文字和資料長度一致;Console 仍可查看原始結果。
    驗收證據
    畫面狀態、清單項目數、Elements 文字與 Console 結果一致。
    卡住先查
    先確認三個 id 存在,再確認 renderButton 的 click 真的呼叫 renderResult。
  6. Step 6

    原始資料快照做最後驗收

    目的
    讓學生不只看到結果,也能證明 mapfilter 沒有把來源 services 改壞。
    修改位置
    solution/files/main.js原始資料快照與 Console
    在整理前保留 services 的 JSON 快照,整理後比較 unchanged 結果。
    預期結果
    Console 的 unchanged 是 true;services 仍有三筆完整物件,推導結果各自是新陣列
    驗收證據
    Console 展開 unchanged、services、names、featuredServices,並能說明四者責任。
    卡住先查
    先搜尋原始快照宣告,再確認比較發生在 mapfilter 之後。
操作層級Live Lab 段落導覽:切換六個實驗步驟

讀碼順序:先找入口,再找被引用的檔案,最後用畫面、DOMConsoleNetwork 或資料結果驗證。

互動問答

先回答目前這一題,再展開解析;完成後按下一題,讓每一次回答都回到檔案或瀏覽器完成驗證。

Q1概念理解 「值(value)」在本堂要解決什麼問題? 本題線索:值;回到名詞卡與 Console 直接印出值,並可搭配 typeof 觀察型別 展開解析收合解析

白話解析:

程式目前拿來使用的一份資料,例如文字、數字或 true/false。 正式來說,JavaScript 運算式計算出的資料,可以被指定給變數、傳給函式或放進物件

對照位置:

回到名詞卡「值」,再看 Console 直接印出值,並可搭配 typeof 觀察型別

預期觀察:

你應該能用自己的話說出:讀程式碼時先問「這裡拿到的是什麼資料?」。

常見錯誤:

不要只回答「它是值」;那是重複名詞,不是說明責任。

立即驗證:

開啟 examples/minimal.html,依序做「開啟 examples/minimal.html,先預測三筆資料與兩筆推薦資料,再按「整理服務資料」;比較畫面、Console 的 services/names/featuredServices,最後按「重設」。」並記下畫面或工具證據。

Q2程式碼閱讀 修改指定規則後,你預測畫面會看到什麼? 本題線索:starter/files/main.js 的 services array;要修改:建立三筆都含 name、price、featured 的服務物件。;觀察:Console 的 services.length、services[0] 與 services[0].price。 展開解析收合解析

白話解析:

先看檔案責任,再預測結果。這一步的目的:先讓學生看懂陣列裡放的是物件,而不是一長段文字;後續每一步都依同一組 property 工作。

對照位置:

對照 Live Lab Step 1,位置是 starter/files/main.js 的 services array;範例內容:const services = [ { name: "到府諮詢", price: 1200, featured: true }, { name: "定期維護", price: 800, featured: false }, { name: "安心檢查", price: 600, featured: true }, ];

預期觀察:

Console 展開 services 看到三筆物件;services.length 是 3,第一筆的 name 是「到府諮詢」。

常見錯誤:

如果只改了檔案但沒有結果,先不要重寫全部;只看 services 的第一個物件,逐字比對 name、price、featured 三個 property

立即驗證:

實際操作後檢查 Console 的 services.length、services[0] 與 services[0].price。。

Q3概念比較 「值」和「型別」在本堂的責任有什麼不同? 本題線索:比較 值 與 型別;操作位置:starter/files/main.js 的 services array 展開解析收合解析

白話解析:

值:程式目前拿來使用的一份資料,例如文字、數字或 true/false。;型別:描述一個值屬於哪一種資料。

對照位置:

對照兩張名詞卡的正式定義:JavaScript 運算式計算出的資料,可以被指定給變數、傳給函式或放進物件。/JavaScript 用來區分文字、數字、布林值物件等資料種類的分類。

預期觀察:

你應該能指出兩者分別出現在哪個檔案或工具,以及哪一個結果會改變。

常見錯誤:

不要把「改變畫面」當成所有技術的責任;先說清楚誰負責結構、呈現、行為或驗收。

立即驗證:

starter/files/main.js 的 services array 做「在 Console 觀察 services[0]、services[0].name 與 services.length。」,再用 Console 三行輸出和陣列展開內容逐一對照。 比較前後差異。

Q4除錯驗收 如果完成操作後結果不對,你會先從哪一個證據開始查? 本題線索:solution/files/main.js原始資料快照與 Console;第一個檢查位置:Console 展開 unchanged、services、names、featuredServices,並能說明四者責任。 展開解析收合解析

白話解析:

先描述症狀,再提出一個最小假設。本堂常見錯誤是:只看畫面顯示正確就宣稱資料沒變,或用 services = featuredServices 取代來源資料。

對照位置:

對照最後一段 Live Lab:solution/files/main.js原始資料快照與 Console;檢查方式:先搜尋原始快照宣告,再確認比較發生在 mapfilter 之後。

預期觀察:

你要能指出一個具體位置,而不是一次修改很多檔案。

常見錯誤:

不要先清快取、重裝工具或複製 Solution;先查看第一個可觀察錯誤。

立即驗證:

重新操作並留下「症狀、證據、假設、單一修正、結果」五項紀錄。

除錯對照表:先看資料形狀,再改一處

看到的症狀第一個證據先檢查什麼
畫面顯示 0 項推薦Console 的 featuredServices確認是否真的宣告 featuredServices,filter callback 是否回傳 service.featured === true。
names 出現 undefinedConsole 展開 services 第一筆逐字比對資料欄位是 name,並確認 map callback 回傳 service.name。
只剩推薦資料,全部服務不見Console 的 services.length確認沒有把 filter 結果指定回 services;推導結果應放在 featuredServices。
按鈕沒有畫面結果Console 第一個錯誤與 Elements確認 #status、#service-list、#featured-list 存在,再確認 renderButton 有 click listener。

常見誤解

本堂任務與驗收

完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。

官方延伸閱讀