Javascript ES6 Iterators建議指南(含實例)

由Arfat Salman發佈


Javascript ES6 Iterators建議指南(含實例)


本文旨在分析理解 Iterators 。 Iterators 是 JavaScript 中的新方法,可以用來循環任意集合。在ES6中登場的Iterators。因其可被廣泛使用,並且已在多處場景派上用場,現已十分流行。

我們從概念上去理解iterators,通過實例講述在何處使用。並且. We’ll also see some of its implementations in JavaScript.

介紹

如果你有下面的數組 ——

const myFavouriteAuthors = [
'Neal Stephenson',
'Arthur Clarke',
'Isaac Asimov',
'Robert Heinlein'
];

有時,你需要獲取這個數組中每一個值,在屏幕上顯示它們,操作它們,或者依據它們做些事情。如果我問你將如何處理?你會說,這很簡單——我循環它們就是了,可以用for__, while__, for-of 或者 這些 循環方法中的任意一個。


Javascript ES6 Iterators建議指南(含實例)


各種循環數組的方法

如果現在不是前面的數組,而是以自定的數據結構保存所有的authors,比如——


Javascript ES6 Iterators建議指南(含實例)


自定數據結構

現在, myFavouriteAuthors 是一個包含了對象 allAuthors 的對象, allAuthors 包含了三個數組,對應key值為 fiction , scienceFiction ,和 fantasy 。 現在如果需要遍歷 myFavouriteAuthors 來獲取所有的作者, 你的方法是什麼? 你可以繼續嘗試一些循環組合來獲取所有數據。

然而,如果你這樣做 —

for (let author of myFavouriteAuthors) { 
console.log(author)
}
// TypeError: {} is not iterable

你會得到一個該對象不是_可迭代的_TypeError。 我們來看看迭代是什麼,以及我們如何使對象可迭代。 在本文的最後,你將知道如何在這種情況下,在 myFavouriteAuthors上,在自定義對象上使用 for-of 循環。

Iterables(可迭代對象) and Iterators(迭代器)

在上一節中看到了問題所在。 沒有方法可以簡單得從我們的自定義對象中獲取所有作者。 我們想要一種方法,通過它我們可以有序地呈現所有內部數據。

讓我們在 myFavouriteAuthors 中添加一個返回所有作者的方法 getAllAuthors 。 像這樣 ——


Javascript ES6 Iterators建議指南(含實例)


getAllAuthors 的實現

這是一個簡單的方法。 它完成了獲得所有作者的當下目標。 但是,這種實現可能會出現一些問題。 比如——

  • getAllAuthors 這個名字非常具體。 如果其他人正在創建他們自己的 myFavouriteAuthors ,他們可能會將其命名為 retrieveAllAuthors 。
  • 作為開發人員,我們始終需要了解將返回所有數據的特定方法。 在這個案例裡,它被命名為 getAllAuthors 。
  • getAllAuthors 返回包含所有作者的字符串數組。 如果另一個開發人員以這種格式返回一個對象數組會怎樣——

[ {name: 'Agatha Christie'}, {name: 'J. K. Rowling'}, ... ]

開發人員必須知道,返回所有數據的方法的 確切名稱和返回類型

如果我們制定一個 規則 ,該方法的 名稱 及其 返回類型是固定且不可更改的 ,這怎麼辦?

讓我們將這個方法命名為—— **iteratorMethod **.

ECMA 採取了類似的步驟,來標準化循環自定義對象的過程。但是,ECMA使用 Symbol.iterator 而不是 iteratorMethod 。 Symbols 提供唯一且不能與其他屬性名稱衝突的名稱。 此外, Symbol.iterator 將返回一個名為 iterator 的對象。 這個迭代器將有一個名為 next 的方法,它將返回一個包含key為 value 和 done 對象,

key value 中將包含當前值。 它可以是任何類型。 done 是布爾值。 它表示是否已獲取所有值。

下圖可能有助於建立 _ iterables __ iterators __ next _ 之間的關係。 這種關係稱為迭代協議。


Javascript ES6 Iterators建議指南(含實例)


iterables, iterators, 和 next之間的關係。

參考 Axel Rauschmayer博士 的 Exploring JS 一書 —

  • _ iterable _是一種數據結構,旨在使其元素可在公用環境被訪問。 它通過實現一個key為 Symbol.iterator 的方法來實現。 該方法是 **iterators **的工廠。 也就是說,它將創建 **iterators **.
  • iterator 是用於遍歷數據結構中元素的指針。

使對象可迭代

正如我們在上一節中所學到的,我們需要實現一個名為 Symbol.iterator 的方法。我們將使用 computed property syntax 來設置這個key。舉一個簡短的例子 —


Javascript ES6 Iterators建議指南(含實例)


可迭代的示例

在第4行,我們創建iterator。 這是一個定義了 next 方法的對象。 next 方法根據 step變量返回對應的值。 在第25行,我們取到 iterator 。 27行,我們調用 next 方法。 接下來我們繼續調用,直到 done 變成'true`。

這正是 for-of 循環中發生的事情。 for-of 循環採用 **iterable **,併為其創建 _ iterator_ 。 不斷調用 next() 直到 done 為真。

JavaScript中的 Iterables

很多東西在JavaScript中都是可迭代的。 它可能不是立等可見的,但如果仔細觀察,是能看到iterables的。

這些都是可迭代的 ——

  • Arraysand TypedArrays
  • Strings —迭代每個字符或 Unicode code-points.
  • Maps —迭代 key-value 組合
  • Sets —迭代它們的元素
  • arguments — 函數中一個類似數組的特殊變量
  • DOM 元素 (實現中)

其他在JS中使用iterables的 ——

  • for-of 循環 — for-of 循環需要迭代。 否則,它將拋出一個 TypeError .
for (const value of iterable) { ... }

  • 數組的解構 ——由於可迭代而發生解構。 我們來看看如何實現。

代碼:

const array = ['a', 'b', 'c', 'd', 'e'];
const [first, ,third, ,last] = array;

相當於

const array = ['a', 'b', 'c', 'd', 'e'];
const iterator = array[Symbol.iterator]();
const first = iterator.next().value
iterator.next().value // Since it was skipped, so it's not assigned
const third = iterator.next().value
iterator.next().value // Since it was skipped, so it's not assigned
const last = iterator.next().value

  • 延展符 (…)

代碼:

const array = ['a', 'b', 'c', 'd', 'e'];
const newArray = [1, ...array, 2, 3];

可以寫成

const array = ['a', 'b', 'c', 'd', 'e'];
const iterator = array[Symbol.iterator]();
const newArray = [1];
for (let nextValue = iterator.next();nextValue.done !== true;nextValue = iterator.next()) {
newArray.push(nextValue.value);
}
newArray.push(2)
newArray.push(3)
  • Promise.all 和 Promise.race 接受Promises上的迭代。
  • Maps and Sets

Map的構造函數將 [key,value] 形式的迭代器轉換為Map,Set的構造函數將可迭代的元素轉換為Set——

const map = new Map([[1, 'one'], [2, 'two']]);
map.get(1)
// one
const set = new Set(['a', 'b', 'c]);
set.has('c');
// true
  • 要理解generator 函數,先理解迭代器。

讓myFavouriteAuthors可迭代

這是一個使myFavouriteAuthors可迭代的實現方式。


Javascript ES6 Iterators建議指南(含實例)


可迭代的實現示例

根據本文的介紹,您可以輕鬆瞭解迭代器的工作方式。 可能有點難以理解它的邏輯,所以,我已經為代碼寫了註釋。 但是,吸收和理解概念的最佳方法是讓這些代碼在瀏覽器或node中運行起來。

如有疑問,歡迎回復! 參考:

  • Dr Axel Rauschmayer 的 ExploringJS
  • MDN 上的 Iterator Protocol

需要前端資料或者想學前端的小夥伴可以私信“前端”“前端資料”免費獲取


分享到:


相關文章: