ES20XX Modern JS 新語言特性筆記 | Array


  1. 說明
    1. Array.of
    2. Array.from
    3. Array find()
    4. Array includes()
    5. Array flat()
    6. Review ES5 Array Method
      1. every()
      2. filter()
      3. map()
      4. reduce()
  2. ECMA JavaScript ES20XX 系列筆記
  3. 參考資料
    1. ES20XX
    2. Node.js Dancing with ES20XX

筆記從 ES2015 / ES2016 / ES2017 / ES2018 / ES2019 / ES2020 以來,JS 所加入的新語言特性。使用的情境新語言特性不僅是為了減少對第三方套件的依賴 (Lodash),也是基於 ESLint 上 Clean Code、Best Practices 規範要求。熟悉新語言特性不僅能夠使 JS 開發更加快速也能夠提升閱讀性。

JavaScript logo

說明

想要先談的幾個新語言特性,都是被 ESLint 糾正或者是開發過程中恰好需要的。本篇筆記為 Modern JS Array 的相關 Property 以及 Method。

Array.of

ES6 的新語法特性,用以解決以往使用 new Array 時候因為參數型別問題產生非預期回傳陣列的問題。但實際在寫 JS 的時候,都是以 Array Literal 的方式使用陣列居多。

Array.from

Array.from 可以處理 Array-Like 物件,並加以轉換成陣列。

例如可以將字串拆解成字元陣列

Array.from('Apple')
// ['A', 'p', 'p', 'l', 'e']

從 Set 或 Map 轉換為陣列

Array.from(new Set([1, 2, 3, 4, 5, 1, 2, 3]))
// [1, 2, 3, 4, 5]

Array.from 可以做為 Map 參數的還原轉換:

Array.from(new Map([[1, 2], [2, 4], [4, 8]]));
// [[1, 2], [2, 4], [4, 8]]

在函式中將 Arguments 轉換為陣列

function foo()
{
  return Array.from(arguments)'
}
foo(1, 2, 3)
// [1, 2, 3]

搭配 Arrow Function 達到 Map 功能

Array.from([1, 2, 3, 4, 5], x => x ** 2)
// [1, 4, 9, 16, 25]

上述範例所使用的 Array Function 中的 Exponentiation Operator 為 ES2016 所加入的語言特性,以往只能使用 Math.Pow 的方式來進行指數運算。

Array find()

以往要在陣列中查詢元素,僅能藉由 indexOf,找到陣列中第一個元素所屬 index 位置。而 Array.find 的參數則是 callback function,可以用條件化的方式來尋找符合的元素,並直接回傳該值而非 index 位置。

[1, 4, 9, 16, 25].find(x => x > 15)
// 16

此外 callback function 可以包含三個參數,分別如下:

element

[1, 4, 9].find((element, index, array) => element == 4)
// 4
[1, 4, 9].find((element, index, array) => element == 5)
// undefined

index

[1, 4, 9].find((element, index, array) => index == 2)
// 9

array

會指向要被 find 的 array 本身。

同樣在 ES6 所加入並且與 find 類別的 Array Method 還有 findIndex,和 find 的使用方式類似,但差別在於回傳的結果是 Index 而非 Element。

Array includes()

在 ES6 所加入的 includes Method 可以用於檢查 element 是否存在於 Array 當中,此外支援 Optional 參數 fromIndex 可以從特定的 Index 後開始檢查。

[0, 1, 2, 3, 4, 5].includes(3)
// true
[0, 1, 2, 3, 4, 5].includes(3, 4)
// false
[0, 1, 2, 3, 4, 5].includes(4, 4)
// true

Array flat()

flat Array 經常作為程式測驗的練習,要求實作能夠展開巢狀 Array 的函式,而在 ES2019 後,Array 原生內建有此 Method,可以用於展開巢狀的 Array,非常方便。

[1,[2,[3]]]
[1,[2,[3]]].flat()
// [1, 2, [3]]
[1,[2,[3]]].flat().flat()
// [1, 2, 3]

或是可以直接指定 Depth,如果參數使用 Infinity 可以直接達到完全展開。

[1,[2,[3]]].flat(3)
// [1, 2, 3]

Review ES5 Array Method

下列 ES5 已經支援的 Array Method 都是有 functional programming 味道的 Array Method,重新溫習以增加在使用上的頻率,減少對於 lodash 的依賴。

every()

every 參數為 callback function,同樣支援 element, index, array 三個參數,例如可以使用下列方式,檢查 Array 中所有的元素是否為從 1 遞增的平方 Array。

[1, 4, 9, 16, 25].every(
  (element,index,array) => element == (index + 1) ** 2
)
// true

與 every() 相似 Method 有 some(),兩者的使用方式類似,參數都是接受 callback function。判斷 true or false 的差別在於,every 相同於 python 的 all 必須要 Array 中所有的元素都符合 callback 才會回傳 true;而 some 類似 python 的 any,只要有其中一個元素符合 callback 就會回傳 true。

filter()

參數同樣是 callback,同樣支援 element, index, array 三個參數,可以使用 filter 檢查 Array 大於 5 的元素或 index 為 0 的元素:

const arr = [1, 4, 9, 16, 25]
arr.filter((element, index) => element >= 5 || index == 0)
// 1, 9, 16, 25

map()

儘管我們已經曾 Array.from 學習到如何達到 map 的功能,但其實在 ES5 對於 Array 已經支援 map,而在使用上 map 的語意也比較明確,因此如果不是特別要處理 array-like 的物件並結合 map 使用,不需要特別使用 Array.from 而是應該使用 map()。

參數同樣是 callback,同樣支援 element, index, array 三個參數。

const arr = [1, 2, 3, 4, 5]
arr.map((element, index) => element ** 2 + index)
// 1, 5, 11, 19, 29

map 也可以用於將物件陣列中的特定 Property 取出,形成新的陣列:

const arrOfObjs = [
    {name: 'Slime', hp: 10},
    {name: 'Dracky', hp: 15},
    {name: 'Golem', hp: 120},
]

arrOfObjs.map((o) => o.name)
// ['Slime', 'Dracky', 'Golem']

reduce()

和上述 every, some, filter, map 有所不同,reduce cabllback function 所支援的參數包含:accumulator, currentValue, currentIndex, array。除了累加數值外,很少使用到 reduce,無論是在寫 python 或者 js。但從範例學到如果要累加物件屬性的數值的時候,reduce 不失為一個好選擇:

let cart = [{
        product: 'Dragon Quest Builder2',
        qty: 1,
        price: 30
    },
    {
        product: 'Two Points University',
        qty: 2,
        price: 10
    },
    {
        product: 'Age of Emppire 2',
        qty: 1,
        price: 10.99
    }
];

reduce 有一個 Optional Value initialValue,可以設定為 accmulator 的初始值,預設是 Object。

let total = cart.reduce(function (accumulator, currentValue) {
    return accumulator 
    + currentValue.qty * currentValue.price;
}, 0);

ECMA JavaScript ES20XX 系列筆記

  1. Array

  2. Spread, Rest & Destructuring

參考資料

ESLint Rules

Airbnb JavaScript Style Guide

JavaScript Tutorial

ES20XX

JavaScript: What’s new in ECMAScript 2019 (ES2019)/ES10?

ES2020 中 Javascript 10 個你應該知道的新功能

Node.js Dancing with ES20XX

查詢 Node.js 各版本對於 Ecma JavaScript 的支援情況。目前主要使用的 Node.js 12.10 對於 ES2019 以前都有相當高的支援情況,所以使用新 Feature 無煩惱。

Node.green