2023-10-18|閱讀時間 ‧ 約 10 分鐘

JavaScript 陣列學習筆記

如果學程式也能像這些甜甜圈一樣美好就好了......

這邊是我初學 JavaScript 陣列時為了怕金魚腦的筆記區,主要的內容會以 Alpha Camp 的教材為主,輔以一些我自己在網路上看到的實用資訊。由於隨時可能學到新知識,這篇筆記將不定期更新。


JavaScript 的陣列其實不是陣列

由於先前我有看過 CS50 的 Data Structure 影片,因此知道陣列是在記憶體當中以線性且連續的方式儲存資料。不過 JavaScript 在初版發布時沒有包含陣列這種資料結構,只有物件 (Object) 可供使用。然而後續大家還是需要有次序的資料結構,所以 JavaScript 硬是弄了個類陣列的物件。透過 typeof 我們便能發現 JavaScript 陣列雖然披著陣列的皮,實質上就是個不折不扣的物件。

有種被欺騙感情的感覺......

運用索引 (index) 存取資料

陣列的最大特點就是能用索引存取資料,我們可以把索引想像成編號,每個陣列都是從 0 開始索引的。只要在陣列名稱後面加上中括號,並於中括號內帶入資料的索引,程式碼就會回傳對應的資料值囉~


知道陣列的長度

JavaScript 陣列提供了眾多操作方法,其中 array.length能快速回傳陣列的長度給我們,回想起當初 CS50 用 C 語言人工算出陣列長度,才發現 JavaScript 果然有方便的地方。


找到陣列的最後一筆資料

既然能快速知道陣列的長度,我們可以透過 array.length 找出陣列的最後一筆資料。

❗由於陣列索引從 0 開始,所以中括號要帶入的是 array.length - 1 ​。

找出陣列最後一筆資料

看起來不錯,但第三行程式碼重複呼叫了 numbers 這個變數。我們可以參考 array.at 更簡潔的寫法,小括號中的 - 1 代表從陣列尾端往回推的第一筆資料。

用更簡潔的寫法取得陣列最後一筆資料~


一次取得陣列中的所有資料值

畢竟我們也長大了,有時候難免全都要陣列的所有資料值,這時候可以搭配迴圈去遍歷陣列每個索引,然後回傳該索引對應的資料值。由於陣列索引是從 0 開始的,加上我們能取得陣列的長度,因此 for 迴圈能帶來不錯的效果。

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}

如果不需要取得資料的索引,for ... of 迴圈提供了更加簡潔的寫法。若要採用這種寫法陣列的命名最好用英文複數比較清楚。

const numbers = [1,2,3,4,5,6,7,8,9,10];

for (let number of numbers) {
console.log(number);
}

操作陣列資料 (新增、刪除)

除了 array.length 之外,JavaScript 還提供了其他好用的操作方法,讓我們自由新增、刪除陣列資料。不過在進入到操作方式的介紹之前,我們需要先認識兩種資料結構:Queue 以及 Stack。JavaScript 陣列支援這兩種方式。


ADT (abstract data type)

ADT 是資料結構的一種類別,這種類別的資料架構僅定義了資料類型的行為 (behaviour),而沒有定義實現的方式 (implementation),像是 Array、List、Map、Queue、Stack、Table、Tree、Vector 都是 ADT。我們可以把 ADT 想像成書這個概念,書在人類定義中是要被用來記錄、閱讀的 (行為),然而根據不同的書寫目的,世界上有成千上萬種書,像是小說、電話簿、工具書、教科書等等……(實現的方式)。


先進先出的 Queue

Queue 是 ADT (abstract data type) 的一種,遵循 FIFO (fitst in first out) 的先進先出原則。什麼是先進先出呢?我們可以把 Queue 想像成餐廳的排隊隊伍。餐廳一定是讓先來排隊的客人先進去用餐,越晚來的客人則越晚能進去,這就是 FIFO 的道理。

如果我們想把東西加入進去,這個動作稱為 enqueue;相對來說,若要把東西從 Queue 取出來,該動作被稱為 dequeue

圖片來自 https://javascript.info/

後進先出的 Stack

相較於 QueueStack 遵循的是 LIFO (last in first out) 的後進先出原則。我們可以想像成是大賣場的推車,通常大家都是先拿最外面的推車。如果我們想把東西加入到 Stack 最上面,這個動作被稱為 push;而把東西從 Stack 最上面抽走的動作則稱為 pop

圖片來自 https://javascript.info/

JavaScript 按順序操作資料

JavaScript 陣列提供了 pushpopshift 這三種操作方法,除此之外,若想要將資料加入到陣列最前面,還有 unshift 可以使用。unshift 的命名也許就是比較 shift 而來的 (?)

圖片來自 Alpha Camp

其中 popshift 的回傳值為被移除的資料值,而 push 和 unshift 則是回傳陣列的新長度,兩方的差別需要特別留意。


從陣列中間操作資料

前面所提到的操作方法都是在陣列頭尾新增或移除資料,如果是想從中間著手的話,可以透過 array.splice 實現。以下是 splice 在劍橋辭典的解釋:

to join two pieces of rope, film, etc. together at their ends in order to form one long piece

splice 的語法比較複雜,有三個參數:

  1. 要操作的陣列索引
  2. 要刪除的資料數量
  3. 要插入的資料值

若是要插入資料,那三個參數都要輸入;倘若只是要移除資料,僅需要輸入前兩項參數即可。無論是插入或移除資料,splice 的回傳值都是變更完成後的陣列。


splice 插入資料

假設今天我們希望在把 99 插入到陣列索引 2,由於沒有要移除任何資料,所以 splice 第二個參數輸入 0 即可。

const nums = [0, 1, 2, 3, 4];
nums.splice(2, 0, 99);
console.log(nums); // [0, 1, 99, 2, 3, 4]


splice 移除資料

假設我們希望從陣列索引 2 開始移除兩筆資料,程式碼會長這樣:

const nums = [0, 1, 2, 3, 4];
const deletedNumbers = nums.splice(2, 2); // 移除索引二和索引三的資料
console.log(deletedNumbers); // [2, 3]


從陣列擷取部分資料

若我們希望從陣列擷取部分資料,然後存放到另一個新陣列的話,不妨參考 array.slicespliceslice 的概念和語法都不太一樣,要特別注意!

slice 有兩個參數:

  • 要從哪個索引開始擷取資料
  • 要在哪個索引結束資料擷取 (不包含該索引)

所以今天如果我們希望擷取 fruits 陣列的第二與第三索引的資料,寫法如下:

const fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
const citrus = fruits.slice(1, 3);

// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']

由此可見,slice 並不會對原先的陣列造成影響,只是把擷取下來的資料複製到新陣列裡面而已。


合併多個陣列

JavaScript 是一個相對寬鬆的語言,所以容易出現資料型別強制轉換 (coercion) 的狀況。比方說,若我們單純用 + 妄想合併陣列,回傳的值將被強制轉換成字串。所以正確的做法應該是使用 array.concat 來合併兩個或是多個陣列 (以半形逗號隔開)。

const num1 = [1, 2, 3];
const num2 = [4, 5, 6];
const num3 = [7, 8, 9];

const numbers = num1.concat(num2, num3);

console.log(numbers);
// results in [1, 2, 3, 4, 5, 6, 7, 8, 9]

這邊請注意 concat 回傳的是一個合併後的新陣列,所以不會對原先的陣列造成影響。


Reference

分享至
成為作者繼續創作的動力吧!
Bonjour à tous,我本身是法文系畢業,這邊會刊登純文組學習網頁開發的筆記。如果能鼓勵更多文組夥伴一起學習,那就太開心了~
從 Google News 追蹤更多 vocus 的最新精選內容從 Google News 追蹤更多 vocus 的最新精選內容

蕭宇廷的沙龍 的其他內容

發表回應

成為會員 後即可發表留言
© 2024 vocus All rights reserved.