今天學的是「一群資料的容器」——陣列。宣告方式是用中括號:
const enemies = ["雜魚", "小怪", "菁英怪", "小BOSS", "魔王"];
要拿出陣列裡的東西,用索引(index),但索引從 0 開始算,不是從 1:
console.log(enemies[0]); // 雜魚
console.log(enemies[1]); // 小怪
console.log(enemies[2]); // 菁英怪
這個「從 0 開始」的習慣,業界有個專門的錯誤名稱叫 off-by-one error(差一錯誤)——新手很容易想成「第一個是 1」,結果拿錯資料或漏看最後一個。
查了一下才知道,JavaScript 從 0 開始算索引,不是全世界的共識,像 Lua、MATLAB、R 這些語言,陣列的第一個位置就是索引 1,不是 0。這讓我想到一個比喻,可以解釋這兩種邏輯的差異:
從 0 開始,像爬樓梯:算的是「距離起點幾步」。 你在 1 樓,爬到 5 樓,實際上只爬了 4 層樓梯(1→2、2→3、3→4、4→5)。陣列的索引 0 代表「距離起點 0 步」,也就是第一個元素;索引 4 代表「距離起點 4 步」,也就是第五個元素。索引本質上是「位移量」,不是「第幾個」。
從 1 開始,像搭電梯:直接按你要的樓層數字。 你不用管實際爬了幾層樓梯,直接按下「5」就到 5 樓。這類語言的索引直接對應「第幾個」,不用换算位移。
JavaScript 選擇「爬樓梯」邏輯,是因為索引在電腦底層原本的意義,就是「從資料起始位置算起,要位移幾步才能找到這筆資料」——這是很多主流語言(C、Java、Python)共同的選擇,但不是唯一的選擇。
我原本試著取 enemies[100],想看看超出範圍會怎樣,結果是 undefined。但這個測法其實不夠精準——100 一看就知道超出範圍,沒有真正測到「差一點點就出界」的臨界點。
改成測 enemies[5] 之後,結果更有意義:陣列有 5 個元素(索引 0 到 4),length 是 5,但 length 這個數字本身,剛好就是第一個不存在的索引。這個「差一個」的臨界點,才是新手最容易誤判的地方——很容易誤以為「陣列有 5 個,那索引應該到 5 吧」,結果 enemies[5] 其實是 undefined。
![插入 day5.png:enemies[100] 測試結果,含 [[Prototype]] 展開畫面](https://ithelp.ithome.com.tw/upload/images/20260907/20184006CW1Q0gDPrC.png)
這裡我多做了一個實驗:先測一次 enemies[5](此時是 undefined),接著 push 一個新元素進去,再測一次同樣的 enemies[5]:
console.log(enemies[5]); // push 之前:undefined
enemies.push("終極魔王");
console.log(enemies[5]); // push 之後:終極魔王
同一行程式碼、同一個索引,因為陣列的內容變了,結果完全不同。這讓我更清楚體會到:陣列的「有效範圍」不是固定的,它會隨著 push 這類操作即時改變——今天的臨界點,明天可能就不是臨界點了。
![插入 day5-2.png:enemies[5] 在 push 前後的不同結果](https://ithelp.ithome.com.tw/upload/images/20260907/20184006AhyfbByAgb.png)
[[Prototype]] 是什麼展開 Console 裡的陣列時,我發現最後多了一行 [[Prototype]]: Array(0),查了才知道:陣列在 JavaScript 裡其實也是一種物件,而每個物件都帶著一條隱藏連結,指向一個「範本物件」,陣列的範本物件叫 Array.prototype——像 .push()、.length 這些功能,不是每個陣列自己各存一份,而是所有陣列共用同一份範本,透過這條隱藏連結去借用。
這個機制叫原型鏈(prototype chain),而且這條鏈不只一層:Array.prototype 自己也有一條 [[Prototype]],指向更基礎、所有物件都通用的 Object.prototype。用比喻理解就是:
你的陣列 → Array 部門手冊(Array.prototype) → 公司總手冊(Object.prototype)
不同的陣列預設都共用同一本「部門手冊」,不會各自長出不同版本;但不同種類的東西(陣列 vs 一般物件)所連結的手冊確實不一樣。這是比較進階的概念,現階段先知道「陣列的方法是透過這條隱藏連結借來的」就夠了。
今天搞懂的事:
length 是總數,但最後一個有效索引是 length - 1
length 本身),不是隨便取一個明顯超出範圍的數字push 這類操作即時改變,同一個索引在不同時間點可能有效也可能無效push、length)是透過 [[Prototype]] 這條隱藏連結,從共用的 Array.prototype 借來的明天繼續學物件——遊戲角色資料要正式登場了。