摘要:我們將從概念上理解迭代器是什么,以及在何處使用它們和示例。同時返回一個名為迭代器的對象,這個迭代器將擁有一個名為的方法,該方法將返回一個具有鍵值為和的對象。下圖可以幫助建立可迭代對象迭代器和之間的關(guān)系,這種關(guān)系稱為迭代協(xié)議。
我們將在本文中分析迭代器。迭代器是在JavaScript中循環(huán)任何集合的一種新方法。它們是在ES6中引入的,由于它們的廣泛用途和在不同地方的使用而變得非常流行。
我們將從概念上理解迭代器是什么,以及在何處使用它們和示例。我們還將看到它在JavaScript中的一些實現(xiàn)。如果我問你,你會怎么做?你會說——很簡單。我將使用 for、while、for-of 或 其它 方法對它們進行循環(huán)。
想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!
簡介假設(shè)你有這個數(shù)組
const myFavouriteAuthors = [ "Neal Stephenson", "Arthur Clarke", "Isaac Asimov", "Robert Heinlein" ];
在某些情況下,希望返回數(shù)組中的所有多帶帶值,以便在屏幕上打印它們、操作它們或?qū)λ鼈儓?zhí)行某些操作。
如下:
現(xiàn)在,假設(shè)你擁有一個自定義數(shù)據(jù)結(jié)構(gòu)來保存所有作者,而不是上面的數(shù)組,如:
mypreferteauthors 是一個對象,它包含另一個對象 allAuthors。allAuthors 包含三個數(shù)組,其中包含 fiction、scienceFiction 和 fantasy。
現(xiàn)在,如果要求你循環(huán)遍歷 myFavouriteAuthors 以獲得所有的作者,你的方法是什么? 你可能會嘗試一些循環(huán)組合來獲得所有數(shù)據(jù)。
但是,如果你這樣做了 ——
for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not iterable
你將得到一個類型錯誤,說明該對象不可迭代。讓我們看看什么是可迭代的,以及如何使對象可迭代。
在本文的最后,你將了解如何在定制對象上使用for-of循環(huán),在本例中是在 mypreferteauthors 上使用 for-of 循環(huán)。
可迭代對象與迭代器 (Iterables and Iterators)在上一節(jié)中看到了問題,從我們的自定義對象中獲取所有的作者是不容易的。我們需要某種方法,通過它我們可以有序地獲取內(nèi)部數(shù)據(jù)。
我們在 mypreferteauthors 中添加一個返回所有作者的方法 getAllAuthors。如:
這是一個簡單的方法。它幫我們完成了獲取所有作者的功能。但是,這種實現(xiàn)可能會出現(xiàn)一些問題:
getAllAuthors 的名稱非常具體。如果其他人正在創(chuàng)建自己的 mypreferteauthors,他們可能會將其命名為retrieveAllAuthors。
作為開發(fā)人員,我們總是需要知道返回所有數(shù)據(jù)的特定方法,在本例中,它被命名為getAllAuthors。
getAllAuthors 返回的是字符串?dāng)?shù)組,如果另一個開發(fā)人員以這種格式返回一個對象數(shù)組,該怎么辦:
[ {name: "Agatha Christie"}, {name: "J. K. Rowling"}, ... ]
開發(fā)人員必須知道返回所有數(shù)據(jù)的方法的確切名稱和返回類型。
如果我們規(guī)定方法的名稱和它的返回類型是固定不變的呢?
讓我們將這個方法命名為 --- iteratorMethod
ECMA 也采取了類似的步驟來標(biāo)準(zhǔn)化在定制對象上循環(huán)的過程。但是,ECMA沒有使用名稱 iteratorMethod,而是使用名稱 Symbol.iterator。Symbols 提供的名稱是唯一的,不能與其他屬性名稱沖突。同時,Symbol.iterator 返回一個名為迭代器的對象,這個迭代器將擁有一個名為next的方法,該方法將返回一個具有鍵值為 value 和 done 的對象。
值鍵 value 包含當(dāng)前值,它可以是任何類型的,done 是布爾值,它表示是否獲取了所有的值。
下圖可以幫助建立可迭代對象、迭代器和next之間的關(guān)系,這種關(guān)系稱為迭代協(xié)議。
根據(jù)Axel Rauschmayer博士的《探索JS》一書:
可迭代是一種數(shù)據(jù)結(jié)構(gòu),它希望使其元素對外部可訪問,通過實現(xiàn)一個關(guān)鍵字是Symbol.iterator的方法來實現(xiàn),該方法是迭代器的工廠,也就是說,它將創(chuàng)建迭代器。
迭代器是一個指針,用于遍歷數(shù)據(jù)結(jié)構(gòu)的元素,我們將使用computed property語法來設(shè)置這個鍵,如下:
建立可迭代對象因此,正如我們在上一節(jié)學(xué)到的,我們需要實現(xiàn)一個名為Symbol.iterator的方法
在第4行,我們創(chuàng)建迭代器。它是一個定義了next方法的對象。next方法根據(jù)step變量返回值。在第25行,我們檢索iterator,27行,我們調(diào)用next方法,直到 done的值為 true。
這正是for-of循環(huán)中發(fā)生的事情,for-of接受一個迭代器,并創(chuàng)建它的迭代器,它會一直調(diào)用next(),直到 done為 true。
JavaScript中可迭代對象(iterable)JavaScript中的很多對象都是可迭代的。它們可能不是很好的察覺,但是如果仔細檢查,就會發(fā)現(xiàn)迭代的特征:
Arrays and TypedArrays
Strings —— 遍歷每個字符或Unicode代碼點
Maps —— 遍歷其鍵-值對
Sets —— 遍歷元素
arguments? —— 函數(shù)中類似數(shù)組的特殊變量
DOM elements (Work in Progress)
JS中使用迭代的其他一些結(jié)構(gòu)是:
for-of -- for-of 循環(huán)需要一個可迭代的對象,否則,它將拋出一個類型錯誤。
for (const value of iterable) { ... }
數(shù)組解構(gòu) -- 由于可迭代性,會發(fā)生析構(gòu)。讓我們來看看:
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 可迭代下面是一個實現(xiàn),它使mypreferteauthors具有可迭代性:
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); // 存儲當(dāng)前類型和索引 let currentAuthorIndex = 0; let currentGenreIndex = 0; return { // Implementation of next() next() { // 根據(jù)當(dāng)前的索引獲取對應(yīng)的作者信息 const authors = genres[currentGenreIndex]; // 當(dāng)遍歷完數(shù)組 authors是,oNotHaveMoreAuthors 為 true const doNothaveMoreAuthors = !(currentAuthorIndex < authors.length); if (doNothaveMoreAuthors) { // 加一繼續(xù)訪問下一個 currentGenreIndex++; // 重置 currentAuthorIndex = 0; } // 如果所有 genres 都遍歷完了結(jié),那么我們需要告訴迭代器不能提供更多的值。 const doNotHaveMoreGenres = !(currentGenreIndex < genres.length); if (doNotHaveMoreGenres) { return { value: undefined, done: true }; } // 如果一切正常,從當(dāng)genre 返回 作者和當(dāng)前作者索引,以便下次,下一個作者可以返回。 return { value: genres[currentGenreIndex][currentAuthorIndex++], done: false } } }; } }; for (const author of myFavouriteAuthors) { console.log(author); } console.log(...myFavouriteAuthors)
通過本文獲得的知識,你可以很容易地理解迭代器是如何工作的,這種邏輯可能有點難以理解。因此,理解這個概念的最佳方法是多多敲死代碼,多多驗證!
你的點贊是我持續(xù)分享好東西的動力,歡迎點贊!
歡迎加入前端大家庭,里面會經(jīng)常分享一些技術(shù)資源。文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99601.html
摘要:前言又稱提供一個全新的迭代器的概念,它允許我們在語言層面上定義一個有限或無限的序列。后者可以被用來幫助我們理解迭代器。但是當(dāng)我們使用迭代器時,這個問題就迎刃而解了。是中的新語法,用來配合迭代器。這是因為數(shù)組的迭代器只返回其中預(yù)期的元素。 前言 EcmaScript 2015 (又稱ES6)提供一個全新的迭代器的概念,它允許我們在語言層面上定義一個(有限或無限的)序列。 暫時先拋開它...
摘要:簡單介紹下規(guī)范里面迭代器相關(guān)的概念。接口指定迭代器對象必須實現(xiàn)一個方法,如下示例偽代碼。方法是否接受參數(shù),在規(guī)范中并不嚴格限定,取決于實現(xiàn)當(dāng)前這個迭代器的對象。表示迭代終結(jié),后續(xù)再調(diào)用當(dāng)前迭代器的方法,返回的對象一律為。 簡單介紹下 ES6 規(guī)范里面迭代器(Iterator)相關(guān)的概念。最近為啥會看到迭代器,是因為看了 fetch 相關(guān)的 Headers 接口,為了實現(xiàn)下 Header...
摘要:沒有顯示顯示顯示關(guān)鍵字迭代器生成器用于馬上退出代碼塊并保留現(xiàn)場,當(dāng)執(zhí)行迭代器的函數(shù)時,則能從退出點恢復(fù)現(xiàn)場并繼續(xù)執(zhí)行下去。迭代器迭代器是一個擁有方法和方法的對象,通過函數(shù)不斷執(zhí)行以關(guān)鍵字分割的代碼段,通過函數(shù)令分割的代碼段拋出異常。 一、前言 第一次看koajs的示例時,發(fā)現(xiàn)該語句 function *(next){..........
摘要:通過生成器創(chuàng)建的迭代器也是可迭代對象,因為生成器默認會為屬性賦值。我們可以用來訪問對象的默認迭代器,例如對于一個數(shù)組獲得了數(shù)組這個可迭代對象的默認迭代器,并操作它遍歷了數(shù)組中的元素。 ES6 新的數(shù)組方法、集合、for-of 循環(huán)、展開運算符(...)甚至異步編程都依賴于迭代器(Iterator )實現(xiàn)。本文會詳解 ES6 的迭代器與生成器,并進一步挖掘可迭代對象的內(nèi)部原理與使用方法 ...
摘要:可迭代對象就具有屬性,它是一種與迭代器密切相關(guān)的對象。它通過指定的函數(shù)可以返回一個作用于附屬對象的迭代器。迭代器特點每次調(diào)用方法時,返回一個數(shù)組,數(shù)組中兩個元素,分別表示鍵和值。示例之輸出輸出輸出之迭代器特點返回集合中存在的每一個鍵。 Iterator由來 不推薦Iterator方法。 Iterator 函數(shù)是一個 SpiderMonkey 專有特性,并且會在某一時刻被刪除。有一點,需...
閱讀 1567·2021-11-17 09:33
閱讀 1116·2021-11-12 10:36
閱讀 2426·2019-08-30 15:54
閱讀 2449·2019-08-30 13:14
閱讀 2924·2019-08-26 14:05
閱讀 3301·2019-08-26 11:32
閱讀 3012·2019-08-26 10:09
閱讀 3007·2019-08-26 10:09