詳解簡(jiǎn)單易懂的 ES6 Iterators 指南和示例
本文旨在分析理解 Iterators。 Iterators 是 JS中的新方法,可以用來循環(huán)任意集合。 在ES6中登場(chǎng)的Iterators。因其可被廣泛使用,并且已在多處場(chǎng)景派上用場(chǎng),我們將從概念上理解迭代器是什么,以及在何處使用它們和示例。我們還將看到它在JS 中的一些實(shí)現(xiàn)。
簡(jiǎn)介
假設(shè)有這樣數(shù)組
const myFavouriteAuthors = [ 'Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein' ];
在某些情況下,希望返回?cái)?shù)組中的所有單獨(dú)值,以便在屏幕上打印它們、操作它們或?qū)λ鼈儓?zhí)行某些操作。
如何處理? 簡(jiǎn)單方法就是使用 for
, while
, for-of
方法。
如下:
現(xiàn)在,假設(shè)你擁有一個(gè)自定義數(shù)據(jù)結(jié)構(gòu)來保存所有authors
myFavouriteAuthors
是一個(gè)對(duì)象,它包含另一個(gè)對(duì)象 allAuthors
。allAuthors
包含三個(gè)數(shù)組,其中包含 fiction
、scienceFiction
和 fantasy
。
現(xiàn)在,如果要求你循環(huán)遍歷 myFavouriteAuthors
以獲得所有的author
,你的方法是什么? 你可能會(huì)嘗試一些循環(huán)組合來獲得所有數(shù)據(jù)。
但是,如果你這樣做了 ——
for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not iterable
你將得到一個(gè)類型錯(cuò)誤,說明該對(duì)象不可迭代。讓我們看看什么是可迭代的,以及如何使對(duì)象可迭代。
可迭代對(duì)象與迭代器 (Iterables and Iterators)
在上一節(jié)中看到了問題,從我們的自定義對(duì)象中獲取所有的author
是不容易的。我們需要某種方法,通過它我們可以有序地獲取內(nèi)部數(shù)據(jù)。
我們?cè)?myFavouriteAuthors
中添加一個(gè)返回所有作者的方法 getAllAuthors
。如:
這是一個(gè)簡(jiǎn)單的方法。它幫我們完成了獲取所有author
的功能。但是,這種實(shí)現(xiàn)可能會(huì)出現(xiàn)一些問題:
getAllAuthors
的名稱非常具體。如果其他人正在創(chuàng)建自己的myFavouriteAuthors
,他們可能會(huì)將其命名為retrieveAllAuthors
。- 作為開發(fā)人員,我們總是需要知道返回所有數(shù)據(jù)的特定方法,在本例中,它被命名為
getAllAuthors
。 getAllAuthors
返回的是字符串?dāng)?shù)組,如果另一個(gè)開發(fā)人員以這種格式返回一個(gè)對(duì)象數(shù)組,該怎么辦:
[ {name: 'Agatha Christie'}, {name: 'J. K. Rowling'}, ... ]
開發(fā)人員必須知道返回所有數(shù)據(jù)的方法的確切名稱和返回類型。
如果我們規(guī)定方法的名稱和它的返回類型是固定不變的呢?
讓我們將這個(gè)方法命名為 --- iteratorMethod
ECMA 也采取了類似的步驟來標(biāo)準(zhǔn)化在定制對(duì)象上循環(huán)的過程。但是,ECMA 沒有使用名稱 iteratorMethod
,而是使用名稱 Symbol.iterator。
Symbols 提供的名稱是唯一的,不能與其他屬性名稱沖突。同時(shí),Symbol.iterator 返回一個(gè)名為迭代器的對(duì)象,這個(gè)迭代器將擁有一個(gè)名為next
的方法,該方法將返回一個(gè)具有鍵值為 value
和 done
的對(duì)象。
值鍵 value
包含當(dāng)前值,它可以是任何類型的,done
是布爾值,它表示是否獲取了所有的值。
下圖可以幫助建立可迭代對(duì)象、迭代器和next
之間的關(guān)系,這種關(guān)系稱為迭代協(xié)議。
根據(jù)Axel Rauschmayer博士的《探索JS》一書:
可迭代是一種數(shù)據(jù)結(jié)構(gòu),它希望使其元素對(duì)外部可訪問,通過實(shí)現(xiàn)一個(gè)關(guān)鍵字是Symbol.iterator
的方法來實(shí)現(xiàn),該方法是迭代器的工廠,也就是說,它將創(chuàng)建迭代器。迭代器是一個(gè)指針,用于遍歷數(shù)據(jù)結(jié)構(gòu)的元素,我們將使用computed property語法來設(shè)置這個(gè)鍵,如下:
使用對(duì)象可迭代
因此,正如我們?cè)谏弦还?jié)學(xué)到的,我們需要實(shí)現(xiàn)一個(gè)名為Symbol.iterator
的方法
在第4行,我們創(chuàng)建迭代器。它是一個(gè)定義了next
方法的對(duì)象。next
方法根據(jù)step
變量返回值。在第25行,我們檢索iterator
,27 行,我們調(diào)用next
方法,直到 done
的值為 true。
這正是for-of
循環(huán)中發(fā)生的事情,for-of
接受一個(gè)迭代器,并創(chuàng)建它的迭代器,它會(huì)一直調(diào)用next(),直到 done
為 true。
JavaScript中可迭代對(duì)象(iterable)
JS 中的很多對(duì)象都是可迭代的。它們可能不是很好的察覺,但是如果仔細(xì)檢查,就會(huì)發(fā)現(xiàn)迭代的特征:
- Arrays and TypedArrays
- Strings —— 遍歷每個(gè)字符或Unicode代碼點(diǎn)
- Maps —— 遍歷其鍵-值對(duì)
- Sets —— 遍歷元素
arguments
—— 函數(shù)中類似數(shù)組的特殊變量- DOM elements (Work in Progress)
JS中使用迭代的其他一些結(jié)構(gòu)是:
for-of
-- for-of 循環(huán)需要一個(gè)可迭代的對(duì)象,否則,它將拋出一個(gè)類型錯(cuò)誤。
for (const value of iterable) { ... }
數(shù)組解構(gòu) -- 由于可迭代性,會(huì)發(fā)生析構(gòu)。讓我們來看看:
const array = ['a', 'b', 'c', 'd', 'e']; const [first, ,third, ,last] = array;
等價(jià)于:
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
擴(kuò)展操作符(…)
const array = ['a', 'b', 'c', 'd', 'e']; const newArray = [1, ...array, 2, 3];
等價(jià)于:
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
接受可迭代對(duì)象
Maps 和 Sets
讓 myFavouriteAuthors 可迭代
下面是一個(gè)實(shí)現(xiàn),它使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]() { // 獲取數(shù)組中的所有作者 const genres = Object.values(this.allAuthors); // 存儲(chǔ)當(dāng)前類型和索引 let currentAuthorIndex = 0; let currentGenreIndex = 0; return { // Implementation of next() next() { // 根據(jù)當(dāng)前的索引獲取對(duì)應(yīng)的作者信息 const authors = genres[currentGenreIndex]; // 當(dāng)遍歷完數(shù)組 authors是,oNotHaveMoreAuthors 為 true const doNothaveMoreAuthors = !(currentAuthorIndex < authors.length); if (doNothaveMoreAuthors) { // 加一繼續(xù)訪問下一個(gè) currentGenreIndex++; // 重置 currentAuthorIndex = 0; } // 如果所有 genres 都遍歷完了結(jié),那么我們需要告訴迭代器不能提供更多的值。 const doNotHaveMoreGenres = !(currentGenreIndex < genres.length); if (doNotHaveMoreGenres) { return { value: undefined, done: true }; } // 如果一切正常,從當(dāng)genre 返回 作者和當(dāng)前作者索引,以便下次,下一個(gè)作者可以返回。 return { value: genres[currentGenreIndex][currentAuthorIndex++], done: false } } }; } }; for (const author of myFavouriteAuthors) { console.log(author); } console.log(...myFavouriteAuthors)
通過本文獲得的知識(shí),你可以很容易地理解迭代器是如何工作的,這種邏輯可能有點(diǎn)難以理解。因此,理解這個(gè)概念的最佳方法是多多敲死代碼,多多驗(yàn)證!
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ES6新特性二:Iterator(遍歷器)和for-of循環(huán)詳解
- ES6中Iterator與for..of..遍歷用法分析
- ES6 迭代器(Iterator)和 for.of循環(huán)使用方法學(xué)習(xí)(總結(jié))
- ES6入門教程之Iterator與for...of循環(huán)詳解
- 詳談ES6中的迭代器(Iterator)和生成器(Generator)
- ES6 Iterator接口和for...of循環(huán)用法分析
- ES6實(shí)現(xiàn)的遍歷目錄函數(shù)示例
- ES6 Iterator遍歷器原理,應(yīng)用場(chǎng)景及相關(guān)常用知識(shí)拓展詳解
相關(guān)文章
JS創(chuàng)建對(duì)象的十種方式總結(jié)
面向?qū)ο笫且环N重要的編程范式,如何靈活的創(chuàng)建對(duì)象,是對(duì)編程基本功的考驗(yàn),本來我們來探討一下JavaScript中創(chuàng)建對(duì)象的十種方式,感興趣的小伙伴可以了解下2023-10-10用JavaScript實(shí)現(xiàn)UrlEncode和UrlDecode的腳本代碼
用js自定義函數(shù)寫的實(shí)現(xiàn)url加密解密的實(shí)現(xiàn)代碼,需要的朋友可以參考下2008-07-07JS實(shí)現(xiàn)具備延時(shí)功能的滑動(dòng)門菜單效果
這篇文章主要介紹了JS實(shí)現(xiàn)具備延時(shí)功能的滑動(dòng)門菜單效果,涉及JavaScript基于鼠標(biāo)事件與時(shí)間函數(shù)實(shí)現(xiàn)頁面樣式延遲變換功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09Javascript 對(duì)象(object)合并操作實(shí)例分析
這篇文章主要介紹了Javascript 對(duì)象(object)合并操作,結(jié)合實(shí)例形式分析了javascript基于jQuery的extend方法、對(duì)象屬性、遍歷賦值等操作實(shí)現(xiàn)對(duì)象合并相關(guān)操作技巧與使用注意事項(xiàng),需要的朋友可以參考下2019-07-07javascript中的return和閉包函數(shù)淺析
這篇文章主要介紹了javascript中的return和閉包函數(shù)淺析,至少可以讓你搞懂那么多()是什么意思,需要的朋友可以參考下2014-06-06