您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“ES6中Iterators的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“ES6中Iterators的示例分析”這篇文章吧。
簡介
假設有這樣數組
const myFavouriteAuthors = [ 'Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein' ];
在某些情況下,希望返回數組中的所有單獨值,以便在屏幕上打印它們、操作它們或對它們執行某些操作。
如何處理? 簡單方法就是使用 for
, while
, for-of
方法。
如下:
現在,假設你擁有一個自定義數據結構來保存所有authors
myFavouriteAuthors
是一個對象,它包含另一個對象 allAuthors
。allAuthors
包含三個數組,其中包含 fiction
、scienceFiction
和 fantasy
。
現在,如果要求你循環遍歷 myFavouriteAuthors
以獲得所有的author
,你的方法是什么? 你可能會嘗試一些循環組合來獲得所有數據。
但是,如果你這樣做了 ——
for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not iterable
你將得到一個類型錯誤,說明該對象不可迭代。讓我們看看什么是可迭代的,以及如何使對象可迭代。
可迭代對象與迭代器 (Iterables and Iterators)
在上一節中看到了問題,從我們的自定義對象中獲取所有的author
是不容易的。我們需要某種方法,通過它我們可以有序地獲取內部數據。
我們在 myFavouriteAuthors
中添加一個返回所有作者的方法 getAllAuthors
。如:
這是一個簡單的方法。它幫我們完成了獲取所有author
的功能。但是,這種實現可能會出現一些問題:
getAllAuthors
的名稱非常具體。如果其他人正在創建自己的 myFavouriteAuthors
,他們可能會將其命名為retrieveAllAuthors
。
作為開發人員,我們總是需要知道返回所有數據的特定方法,在本例中,它被命名為getAllAuthors
。
getAllAuthors
返回的是字符串數組,如果另一個開發人員以這種格式返回一個對象數組,該怎么辦:
[ {name: 'Agatha Christie'}, {name: 'J. K. Rowling'}, ... ]
開發人員必須知道返回所有數據的方法的確切名稱和返回類型。
如果我們規定方法的名稱和它的返回類型是固定不變的呢?
讓我們將這個方法命名為 --- iteratorMethod
ECMA 也采取了類似的步驟來標準化在定制對象上循環的過程。但是,ECMA 沒有使用名稱 iteratorMethod
,而是使用名稱 Symbol.iterator。
Symbols 提供的名稱是唯一的,不能與其他屬性名稱沖突。同時,Symbol.iterator 返回一個名為迭代器的對象,這個迭代器將擁有一個名為next
的方法,該方法將返回一個具有鍵值為 value
和 done
的對象。
值鍵 value
包含當前值,它可以是任何類型的,done
是布爾值,它表示是否獲取了所有的值。
下圖可以幫助建立可迭代對象、迭代器和next
之間的關系,這種關系稱為迭代協議。
根據Axel Rauschmayer博士的《探索JS》一書:
可迭代是一種數據結構,它希望使其元素對外部可訪問,通過實現一個關鍵字是Symbol.iterator
的方法來實現,該方法是迭代器的工廠,也就是說,它將創建迭代器。迭代器是一個指針,用于遍歷數據結構的元素,我們將使用computed property語法來設置這個鍵,如下:
使用對象可迭代
因此,正如我們在上一節學到的,我們需要實現一個名為Symbol.iterator
的方法
在第4行,我們創建迭代器。它是一個定義了next
方法的對象。next
方法根據step
變量返回值。在第25行,我們檢索iterator
,27 行,我們調用next
方法,直到 done
的值為 true。
這正是for-of
循環中發生的事情,for-of
接受一個迭代器,并創建它的迭代器,它會一直調用next(),直到 done
為 true。
JavaScript中可迭代對象(iterable)
JS 中的很多對象都是可迭代的。它們可能不是很好的察覺,但是如果仔細檢查,就會發現迭代的特征:
Arrays and TypedArrays
Strings —— 遍歷每個字符或Unicode代碼點
Maps —— 遍歷其鍵-值對
Sets —— 遍歷元素
arguments
? —— 函數中類似數組的特殊變量
DOM elements (Work in Progress)
JS中使用迭代的其他一些結構是:
for-of
-- for-of 循環需要一個可迭代的對象,否則,它將拋出一個類型錯誤。
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
接受可迭代對象
Maps 和 Sets
讓 myFavouriteAuthors 可迭代
下面是一個實現,它使myFavouriteAuthors
具有可迭代性:
const myFavouriteAuthors = { allAuthors: { fiction: [ 'Agatha Christie', 'J. K. Rowling', 'Dr. Seuss' ], scienceFiction: [ 'Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein' ], fantasy: [ 'J. R. R. Tolkien', 'J. K. Rowling', 'Terry Pratchett' ], }, [Symbol.iterator]() { // 獲取數組中的所有作者 const genres = Object.values(this.allAuthors); // 存儲當前類型和索引 let currentAuthorIndex = 0; let currentGenreIndex = 0; return { // Implementation of next() next() { // 根據當前的索引獲取對應的作者信息 const authors = genres[currentGenreIndex]; // 當遍歷完數組 authors是,oNotHaveMoreAuthors 為 true const doNothaveMoreAuthors = !(currentAuthorIndex < authors.length); if (doNothaveMoreAuthors) { // 加一繼續訪問下一個 currentGenreIndex++; // 重置 currentAuthorIndex = 0; } // 如果所有 genres 都遍歷完了結,那么我們需要告訴迭代器不能提供更多的值。 const doNotHaveMoreGenres = !(currentGenreIndex < genres.length); if (doNotHaveMoreGenres) { return { value: undefined, done: true }; } // 如果一切正常,從當genre 返回 作者和當前作者索引,以便下次,下一個作者可以返回。 return { value: genres[currentGenreIndex][currentAuthorIndex++], done: false } } }; } }; for (const author of myFavouriteAuthors) { console.log(author); } console.log(...myFavouriteAuthors)
通過本文獲得的知識,你可以很容易地理解迭代器是如何工作的,這種邏輯可能有點難以理解。因此,理解這個概念的最佳方法是多多敲死代碼,多多驗證!
以上是“ES6中Iterators的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。