LESSON-15 · 零基礎學生教材
JavaScript 基礎:陣列、物件與資料整理
完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。
先理解:這堂課解決什麼問題?
商家不只一項服務,資料若散落在多個變數中,新增方案與篩選都會變得困難。
本堂要完成:完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。
學習邊界:先完成「用陣列與物件整理服務資料並產生可用結果」,不提前引入尚未教過的框架或建置工具。
先備知識與操作環境
本堂先備:不要求先會陣列或物件;只要知道如何用編輯器儲存檔案、用瀏覽器開啟 files/index.html、按按鈕,並在 DevTools Console 讀取值。先用 examples/minimal.html 觀察三筆資料,再開始 Starter。
- 檔案位置:先找到
starter/files/main.js、services 陣列、service 物件、map/filter,再從本頁的最小實驗開始。 - 瀏覽器:開啟最小實驗與階段頁;每次修改後儲存並重新整理。
- DevTools:依本堂內容使用 Elements、Styles、Computed、Console 或 Network,記下第一個可觀察證據。
- 操作習慣:每次只修改一個檔案或一個責任,先預測、再操作、最後驗收。
先做最小實驗:先看見結果
這不是期末網站,而是一個可以直接看到本堂核心結果的最小實驗。先完成一次操作,再回到檔案和名詞卡對照。
- 入口:開啟
examples/minimal.html。 - 操作:開啟
examples/minimal.html,先預測三筆資料與兩筆推薦資料,再按「整理服務資料」;比較畫面、Console 的 services/names/featuredServices,最後按「重設」。 - 預期:按整理後看到三筆全部服務、兩筆推薦服務,#status 顯示「共 3 項服務,推薦 2 項」,Console 展開三個資料結果;按重設後清單清空且狀態回到「尚未整理」。
- 重設:按「重設」回到初始狀態,或重新整理
examples/minimal.html;這份示範頁只讀,不要直接修改。
學生練習流程
依序完成每一張卡;目前只聚焦一個步驟,先操作,再用可觀察證據確認結果。
-
1
最小實驗
先開啟examples/minimal.html,按「整理服務資料」與「重設」,記下畫面、Console 與 Elements 各自提供的證據。 -
2
名詞
回到名詞卡,依序說出 value/type、array、object、property、index、length;先用 services[0].name 讀一筆資料,不急著寫 map。 -
3
Starter
把 Starter 複製到自己的工作資料夾,先完成三筆物件資料,再完成 names 的 map;每一步只修改main.js的一個區塊,按按鈕並重新整理驗收。 -
4
Checkpoint
前往 Checkpoint,先按整理看見推薦數量不正確,再只修正main.js的 CHECKPOINT-1;確認 filter 的 predicate 使用service.featured === true。 -
5
Solution
前往 Solution,逐檔對照資料宣告、map、filter、renderResult 與重設流程;用 Console 展開 services、names、featuredServices,確認原始 services 仍是三筆。 -
6
變體驗收
完成價格區間變體與獨立挑戰,留下資料形狀、操作前後、畫面/Console/Elements 證據;本堂不加入 fetch、API、框架或完整服務卡元件,下一堂再接 DOM 渲染。
檔案地圖:每個位置負責什麼?
先不要急著背檔名;請把檔案位置和責任連起來。你在階段頁會看到同一份檔案的可執行版本。
starter/files/main.jsJavaScript 腳本:放置本堂「用陣列與物件整理服務資料並產生可用結果」相關的互動邏輯。services 陣列服務資料集合:保存多筆可被畫面渲染的服務資料。service 物件單筆服務資料:用欄位描述名稱、價格或內容。map/filter資料整理方法:轉換清單或篩選符合條件的項目。
先學會這些詞
先從名詞、英文與白話意思開始;每次只展開一張名詞卡,再對照正式定義、範例與驗收證據。專業術語、語法、檔案路徑會使用不同樣式。第一次遇到術語時,先回到這裡,不要靠猜。
資料與型別
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 白話意思:最初建立、後面步驟拿來整理的資料。 展開查看正式定義、範例與驗收證據
- 正式定義
- 在資料轉換流程中作為來源、應保持責任清楚的輸入集合。
- 什麼時候用
- 要比較 map/filter 前後結果,或避免後續步驟改壞來源時。
- 最小範例
- 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 表示目前有三筆服務。
- 可觀察證據
- Console 的 length 與畫面顯示的資料筆數一致。
- 容易混淆
- 和最後一個 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 白話意思:交給 map 或 filter,讓它在處理每一筆資料時呼叫的函式。 展開查看正式定義、範例與驗收證據
- 正式定義
- 作為參數傳入另一個函式,由接收方在指定時機執行的函式。
- 什麼時候用
- 看到 map((service) => ...) 或 filter((service) => ...) 時。
- 最小範例
(service) => service.name 是 map 用來處理每筆服務的 callback。- 可觀察證據
- 在 callback 裡加 console.log,觀察它被呼叫的次數與收到的資料。
- 容易混淆
- 和一般函式呼叫混淆;callback 先被交出去,何時執行由 map 或 filter 決定。
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:逐段讀碼與驗證
每一步只回答五件事:為什麼做、改哪裡、會看到什麼、用什麼證據確認、卡住先查什麼。
-
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。
-
Step 2
用 index 與 property 讀一筆資料
- 目的
- 把「位置」和「欄位」分開,避免把 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;不要同時改動資料宣告。
-
Step 3
用 map 產生名稱新陣列
- 目的
- 理解 map 的工作是逐筆轉換,結果會是新的陣列,不能和 filter 的保留條件混在一起。
- 修改位置
starter/files/main.js的 map result
讓 map callback 回傳每筆 service.name。- 預期結果
- Console 顯示 ["到府諮詢", "定期維護", "安心檢查"];names 有三項,services 仍保留 price 與 featured。
- 驗收證據
- Console 的 names.length === services.length,以及原始 services 仍可展開。
- 卡住先查
- 只讀 callback 的最後一段,確認它回傳 service.name,而不是整個 service。
-
Step 4
用 filter 與明確 predicate 找推薦服務
- 目的
- 讓學生把「轉換」和「挑選」拆開,並看懂 === true 是比較不是賦值。
- 修改位置
checkpoint/files/main.js的 filter predicate
用 service.featured === true 產生 featuredServices,不覆蓋 services。- 預期結果
- featuredServices 只包含到府諮詢與安心檢查兩筆;services.length 仍是 3。
- 驗收證據
- Console 展開 featuredServices、確認兩筆的 featured 都是 true,並再次觀察 services。
- 卡住先查
- 只檢查 filter callback 回傳的條件是否為 service.featured === true。
-
Step 5
把資料結果接到可觀察的畫面
- 目的
- 用最少的 DOM 支援讓學生看見資料處理結果;本堂重點仍是資料,不延伸完整卡片元件。
- 修改位置
starter/files/index.html的 #status、#service-list、#featured-list 與main.js的 renderResult
點擊整理按鈕後,以資料長度更新 status,並以清單顯示全部與推薦服務。- 預期結果
- 畫面顯示三筆全部服務、兩筆推薦服務,狀態文字和資料長度一致;Console 仍可查看原始結果。
- 驗收證據
- 畫面狀態、清單項目數、Elements 文字與 Console 結果一致。
- 卡住先查
- 先確認三個 id 存在,再確認 renderButton 的 click 真的呼叫 renderResult。
-
Step 6
用原始資料快照做最後驗收
- 目的
- 讓學生不只看到結果,也能證明 map 與 filter 沒有把來源 services 改壞。
- 修改位置
solution/files/main.js的原始資料快照與 Console
在整理前保留 services 的 JSON 快照,整理後比較 unchanged 結果。- 預期結果
- Console 的 unchanged 是 true;services 仍有三筆完整物件,推導結果各自是新陣列。
- 驗收證據
- Console 展開 unchanged、services、names、featuredServices,並能說明四者責任。
- 卡住先查
- 先搜尋原始快照宣告,再確認比較發生在 map/filter 之後。
讀碼順序:先找入口,再找被引用的檔案,最後用畫面、DOM、Console、Network 或資料結果驗證。
互動問答
先回答目前這一題,再展開解析;完成後按下一題,讓每一次回答都回到檔案或瀏覽器完成驗證。
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;檢查方式:先搜尋原始快照宣告,再確認比較發生在 map/filter 之後。
預期觀察:
你要能指出一個具體位置,而不是一次修改很多檔案。
常見錯誤:
不要先清快取、重裝工具或複製 Solution;先查看第一個可觀察錯誤。
立即驗證:
重新操作並留下「症狀、證據、假設、單一修正、結果」五項紀錄。
除錯對照表:先看資料形狀,再改一處
| 看到的症狀 | 第一個證據 | 先檢查什麼 |
|---|---|---|
| 畫面顯示 0 項推薦 | Console 的 featuredServices | 確認是否真的宣告 featuredServices,filter callback 是否回傳 service.featured === true。 |
| names 出現 undefined | Console 展開 services 第一筆 | 逐字比對資料欄位是 name,並確認 map callback 回傳 service.name。 |
| 只剩推薦資料,全部服務不見 | Console 的 services.length | 確認沒有把 filter 結果指定回 services;推導結果應放在 featuredServices。 |
| 按鈕沒有畫面結果 | Console 第一個錯誤與 Elements | 確認 #status、#service-list、#featured-list 存在,再確認 renderButton 有 click listener。 |
常見誤解
- 看到畫面沒有變化,不代表程式沒執行;先確認檔案、路徑、元素與狀態證據。
- 能複製 Solution 不代表理解;請先說出修改哪個檔案、預期哪個結果、用什麼證據確認。
- 本堂只使用原生 HTML、CSS、JavaScript 與瀏覽器 DevTools;核心是陣列、物件、property、map、filter 與可觀察結果,非同步、API、框架、npm 與完整 DOM 元件都延後。
本堂任務與驗收
完成結構一致的服務資料,能依條件整理名稱與推薦清單,並以畫面和 Console 證明原始陣列沒有被意外改寫。
- 能用 三筆資料與欄位 留下可重現證據。
- 能用 map 名稱結果 留下可重現證據。
- 能用 filter 推薦結果 留下可重現證據。
- 能用 畫面狀態 留下可重現證據。
- 能用 原陣列未被意外改寫 留下可重現證據。
- Starter、Checkpoint、Solution 的入口都能開啟並知道三者差異。
- 遇到問題時能先寫出症狀,再檢查一個最小假設。