0%

JS 迴圈升級的陣列 Array 方法 forEach()

參加讀書會是個可以讓自己和一群喜歡同一個技術領域的夥伴一起學習的方法,透過讀書會,去了解與深入書中所要表達的內容。
目前進行與參與的讀書會有「Javascript 大全」和「Javascript 忍者」兩本數,雖然「Javascript 大全」不包含很重要的 ES6 部分,但是能夠更全面了解 JS 的演變與歷史,將來在看不同版本的程式碼時,應該可以較為清楚的理解。而「Javascript 忍者」這本是許多前輩推崇的一本好書,雖然以目前的階段來說頗硬,但多了解 JS 深度也是將來會去面對的,將來也勢必會再重讀這一本書,所以就提早了解概況吧。

本篇是主講「Javascript 大全」 裡第七章「陣列」的筆記,僅作為紀錄。

陣列是什麼

陣列:是一組有序群集,由中括號[ ]包圍,裡面的元素為「值」(value),值得位置為「索引」(index)。
陣列元素可是任何型別的資料。
索引值從 0 開始、最高可是 4294967294、最大陣列元素數 4,294,967,295。
陣列繼承自Array.prototype

創建陣列

使用字面值(array literal)

1
2
3
let empty = []; 
let primes = [2, 3, 5,7, 11]
let misc = [1.1, true, "a", ] // misc.length -> 3
  • 自面值可以是任意運算式

    1
    2
    let kilo = 1000;
    let demiKilos = [kilo * 0.5, kilo * 1.5, kilo * 2.5]
  • 自面值可包含物件、陣列本身

    1
    2
    let arr1 = [1, 2, 3]
    let arr2 = [1, 2, { name: "Ayda", city: "Paris", luckyNumbers :[24,42,15]}]

使用 Array()建構式

  • 不帶引數

    1
    let arr = new Array()
  • 帶引數,引數為陣列長度

    1
    2
    let arr = new Array(8)
    // 注意:陣列中未有值
  • 指定陣列值

    1
    let arr = new Array(1, 2, 3, "Hello")

讀取與寫入陣列元素

[ ] 運算子

  • 陣列是特化物件,可用來存取陣列元素的中括號。 -> arr[索引值位置]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    let arr = ["Hello"]
    let value = arr[0]
    arr[1] = 168
    let i = 3 // index
    arr[i] = 4

    arr[i+1] = "Hi" // 索引值為四
    arr[arr[i]] = arr[0] // 把arr[0]的值,賦值給等同索引值的4
    arr //  ["Hello", 168, empty, 4, "Hello"]
  • 與存取物件相同,JS 會將指定的陣列索引轉成字串,再將此字串當成特性名稱。

    1
    2
    3
    let obj = {}
    obj[1] = "one"
    obj // {1: "one"}

== 陣列裡的「特色名稱」-> index ? == 其實不一樣

  • 特色名稱小於 2 的 32 次方(非負數)都會計算入length屬性內,其餘都成為「物件特性名稱」
  • 陣列索引(array index) !== 物件特性名稱(object property name)
  • 依索引查找的元素不存在時為undefined
    1
    2
    3
    let arr = [true,false]
    arr[2] // undefined
    arr[-1] // undefined

稀疏陣列

  • 不具有從 0 開始的索引
  • 即使是稀疏陣列,也會被計算至length屬性
    1
    2
    3
    4
    let arr1 = [,] // 沒元素,但 length 為 1
    let arr2 = [undefined] // undefined 為元素、length 為 1
    0 in arr1 // false
    0 in arr2 // true

陣列長度

  • 只要在我們想知道的陣列變數,以方法的方式加上.length。回傳回來的就是這個陣列的長度。

  • 不管是密集或稀疏陣列,長度(length)永遠大於索引值(index)。

    1
    2
    let arr = ["hi","ho","woops","ciao"];
    arr.length // 4
  • 如果重新指定長度,.length,原本有的會被刪除,沒有的會以空的補上而成為稀疏陣列。

    1
    2
    3
    4
    5
    6
    arr = [1,2,3,4,5]
    arr // [1, 2, 3, 4, 5]
    arr.length = 10
    arr // [1, 2, 3, empty × 7]
    arr.length = 3
    arr // [1, 2, 3]
  • 可指定長度為「唯讀」:object.defineProperty(),改變後不可刪元素。

    1
    2
    3
    4
    5
    6
    let arr = [1,2,3,4,5]
    Object.defineProperty(arr, 'length' ,{
    writable: false
    })
    arr.length = 0
    arr // [1, 2, 3, 4, 5]

新增或刪除陣列元素

新增陣列元素

  • 把值指定給新索引

    1
    2
    3
    let arr = []
    arr[0] = 'Hi'
    arr[1] = 'Hello'
  • 使用push() 從尾端新增

    1
    2
    arr.push('ciao')
    arr // ["Hi", "Hello", "ciao"]
  • 使用unshift() 從前端新增

    1
    2
    arr.unshift("你好")
    arr // ["你好", "Hi", "Hello", "ciao"]



刪除陣列元素

  • 使用 delete 運算子,長度不變

    1
    2
    3
    4
    let arr = [1,2,3,4,5]
    delete arr[1] // true
    arr // [1, empty, 3, 4, 5]
    arr.length // 5
  • 使用 length 重新指定長度

    1
    2
    arr.length = 4
    arr // [1, empty, 3, 4]
  • 使用 pop() 刪除,長度減 1 回傳刪除值 長度改變

    1
    2
    arr.pop()
    arr // [1, empty, 3]
  • 使用 shift() 從開頭刪除 1個元素 長度改變

    1
    2
    arr.shift()
    arr // [empty, 3]
  • 使用 splice() 插入、刪除、取代 會改變長度

    1
    2
    3
    let arr = [1,2,3,4,5]
    arr.splice(1,2) // 從index 1 切下 2 個元素 [2, 3]
    arr // [1, 4, 5]

遍歷陣列之迭代

  • 使用 for 迴圈

    1
    2


  • 使用 for/in 迴圈,稀疏陣列元素不會被迭代

  • 如果迭代順序對演算法很重要,請使用 for 迴圈

  • 使用 forEach():將每個元素傳給指定的函式處理

多維陣列

javascript 並不支持真正的二維陣列,但可使用陣列中的陣列來模擬。

陣列方法

方法 功能 回傳 原陣列
join() 將陣列的所有元素轉成字串並串接起來 回傳結果字串 原陣列不改變
reverse() 倒轉陣列的順序 回傳到轉後的陣列 原陣列改變
sort() 在原陣列上將元素排序 回傳排序後的陣列 原陣列改變
concat() 將調用此方法的陣列連同引數回傳回來 創建並回傳一個新陣列 原陣列不改變
slice() 回傳指定陣列的切片 回傳切片下來的陣列 原陣列不改變
splice() 插入或移除陣列元素 回傳由它刪除掉的元素 原陣列改變
push() 在陣列尾端加入元素 回傳陣列的新長度 原陣列改變
pop() 在陣列尾端刪除元素 回傳它移除掉的元素 原陣列改變
unshift() 在陣列前端加入元素 回傳陣列的新長度 原陣列改變
shift() 在陣列前端刪除元素 回傳它移除掉的元素 原陣列改變
toString() 將每個陣列元素轉成字串 回傳字串 原陣列不改變
toLocaleString() toString()的本地化 回傳本地化後的字串 原陣列不改變
1
2
3
4
 // 日幣
let prices = ['300', 500, 8236, 42];
prices.toLocaleString('ja-JP',{style:'currency',currency: 'JPY'});
// "300,¥500,¥8,236,¥42"

ES5 陣列方法

  • 這些方法的第一個引數大多是函式,它會對陣列中每一個元素都調用一次這個函式。
  • 不會對稀疏陣列裡不存在的元素起作用。
  • 第一個參數的函式引數通常有三個:陣列元素值、該陣列元素的索引、陣列本身。
  • 這些當成第一引數的函式,也接受額外第二引數,如有指定此引數,傳入的函式會被當作第二引數的方法來調用–>傳入的第二引數會變成傳入函式內的this關鍵字的值。
  • 不會修改調用他們的陣列,如果傳函式給這些方法,就有可能修改陣列。
方法 功能 回傳 原陣列
join() 將陣列的所有元素轉成字串並串接起來 回傳結果字串 原陣列不改變
forEach() 逐一查用陣列元素,對每個元素調用指定的函式 回傳調用後的陣列 原陣列改變
map() 將陣列每個元素,逐一傳給指定的函式 回傳調用後的陣列 原陣列不改變
filter() 將陣列每個元素,逐一傳給指定的函式所給的條件 回傳符合條件組成的陣列 原陣列不改變
every() 將指定的函式套用在每個陣列元素上 回傳 true 或 false 原陣列不改變
some() 將指定的函式套用在每個陣列元素上 回傳 true 或 false 原陣列不改變
reduce() 依指定的函式,結合陣列的元素產生一個值 回傳產生值得結果 原陣列不改變
reduceRight() 依指定的函式,(右至左)結合陣列的元素產生一個值 回傳產生值得結果 原陣列不改變
indexOf() 根據指定的值在陣列中(從頭到尾)搜尋元素 有找到回喘該元素索引值,沒找到回傳-1 原陣列不改變
lastIndexOf() 根據指定的值在陣列中(從尾到頭)搜尋元素 有找到回喘該元素索引值,沒找到回傳-1 原陣列不改變

陣列型別

判斷是否為陣列,使用Array.isArray()

類陣列物件(array-like)

物件,為它加上length屬性 -> 類陣列物件(array-like)
typeof 來查看陣列,會得到物件 object,但到底陣列和其他物件有什麼不同?最大的不同是陣列有:

  • length這個特殊屬性
  • Array.prototype繼承過來的許多實用的方法
  • 陣列的class屬性值為Array這幾點吧。

但是所謂的「類陣列」(Array-like) 也是如此嗎?並不是。

1
2
3
4
5
6
7
8
9
10
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
push: Array.prototype.push,
splice: Array.prototype.splice
}
obj.push('d');
obj; // {0: "a", 1: "b", 2: "c", 3: "d", length: 4, push: ƒ}

作為陣列的字串

  • 字串的行為如唯獨的陣列。

    讀取字串裡個別的字元方法:

  • 使用 charAt()
  • 使用中括號 []

字串是不可變的(immutable)值,如果把他們當成陣列,他們會視為唯讀的陣列。
push(), sort(), reverse(), splice() 會修改陣列的方法,不能用在字串上。

自我推薦:JavaScript之一定要瞭解的 Array 與方法 :: 第 11 屆 iT 邦幫忙鐵人賽

推薦:JavaScript 陣列(Array)的方法 - HackMD by 鵬化