摘要:有兩個(gè)協(xié)議可迭代協(xié)議和迭代器協(xié)議。為了變成可迭代對(duì)象,一個(gè)對(duì)象必須實(shí)現(xiàn)或者它原型鏈的某個(gè)對(duì)象必須有一個(gè)名字是的屬性迭代器協(xié)議該迭代器協(xié)議定義了一種標(biāo)準(zhǔn)的方式來(lái)產(chǎn)生一個(gè)有限或無(wú)限序列的值。
ECMAScript 2015的幾個(gè)補(bǔ)充,并不是新的內(nèi)置或語(yǔ)法,而是協(xié)議。這些協(xié)議可以被任何遵循某些約定的對(duì)象來(lái)實(shí)現(xiàn)。可迭代協(xié)議
有兩個(gè)協(xié)議:可迭代協(xié)議和迭代器協(xié)議。
可迭代協(xié)議允許 JavaScript 對(duì)象去定義或定制它們的迭代行為, 例如(定義)在一個(gè) for..of 結(jié)構(gòu)中什么值可以被循環(huán)(得到)。一些內(nèi)置類型都是內(nèi)置的可迭代對(duì)象并且有默認(rèn)的迭代行為, 比如 Array or Map, 另一些類型則不是 (比如Object) 。
Iterator 接口的目的,就是為所有數(shù)據(jù)結(jié)構(gòu),提供了一種統(tǒng)一的訪問機(jī)制,即for...of循環(huán)(詳見下文)。當(dāng)使用for...of循環(huán)遍歷某種數(shù)據(jù)結(jié)構(gòu)時(shí),該循環(huán)會(huì)自動(dòng)去尋找 Iterator 接口,調(diào)用Symbol.iterator方法,返回該對(duì)象的默認(rèn)遍歷器。
ES6 規(guī)定,默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator屬性,或者說(shuō),一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有Symbol.iterator屬性,就可以認(rèn)為是“可迭代的”(iterable)。Symbol.iterator屬性本身是一個(gè)函數(shù),就是當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的遍歷器生成函數(shù)。執(zhí)行這個(gè)函數(shù),就會(huì)返回一個(gè)遍歷器。
為了變成可迭代對(duì)象, 一個(gè)對(duì)象必須實(shí)現(xiàn)(或者它原型鏈的某個(gè)對(duì)象)必須有一個(gè)名字是 Symbol.iterator 的屬性:
迭代器協(xié)議該迭代器協(xié)議定義了一種標(biāo)準(zhǔn)的方式來(lái)產(chǎn)生一個(gè)有限或無(wú)限序列的值。
JavaScript 原有的表示“集合”的數(shù)據(jù)結(jié)構(gòu),主要是數(shù)組(Array)和對(duì)象(Object),ES6 又添加了Map和Set。這樣就有了四種數(shù)據(jù)集合,用戶還可以組合使用它們,定義自己的數(shù)據(jù)結(jié)構(gòu),比如數(shù)組的成員是Map,Map的成員是對(duì)象。這樣就需要一種統(tǒng)一的接口機(jī)制,來(lái)處理所有不同的數(shù)據(jù)結(jié)構(gòu)。
迭代器(Iterator)就是這樣一種機(jī)制。它是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)。
Iterator 的作用有三個(gè):一是為各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問接口;二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;三是 ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi)。
Iterator 的遍歷過程是這樣的。
創(chuàng)建一個(gè)指針對(duì)象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置。也就是說(shuō),遍歷器對(duì)象本質(zhì)上,就是一個(gè)指針對(duì)象。
第一次調(diào)用指針對(duì)象的next方法,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個(gè)成員。
第二次調(diào)用指針對(duì)象的next方法,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個(gè)成員。
不斷調(diào)用指針對(duì)象的next方法,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置。
每一次調(diào)用next方法,都會(huì)返回?cái)?shù)據(jù)結(jié)構(gòu)的當(dāng)前成員的信息。具體來(lái)說(shuō),就是返回一個(gè)包含value和done兩個(gè)屬性的對(duì)象。其中,value屬性是當(dāng)前成員的值,done屬性是一個(gè)布爾值,表示遍歷是否結(jié)束。
var someString = "hi"; typeof someString[Symbol.iterator]; // "function" var iterator = someString[Symbol.iterator](); iterator + ""; // "[object String Iterator]" iterator.next() // { value: "h", done: false } iterator.next(); // { value: "i", done: false } iterator.next(); // { value: undefined, done: true }
原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下。
Array
Map
Set
String
TypedArray
函數(shù)的 arguments 對(duì)象
NodeList 對(duì)象
注意對(duì)象是不具備 Iterator 接口的,一個(gè)對(duì)象如果要具備可被for...of循環(huán)調(diào)用的 Iterator 接口,就必須在Symbol.iterator的屬性上部署遍歷器生成方法(原型鏈上的對(duì)象具有該方法也可)。
調(diào)用 Iterator 接口的場(chǎng)合有一些場(chǎng)合會(huì)默認(rèn)調(diào)用 Iterator 接口(即Symbol.iterator方法),除了下文會(huì)介紹的for...of循環(huán),解構(gòu)賦值, 擴(kuò)展運(yùn)算符其實(shí)也會(huì)調(diào)用默認(rèn)的Iterator 接口。
實(shí)際上,這提供了一種簡(jiǎn)便機(jī)制,可以將任何部署了 Iterator 接口的數(shù)據(jù)結(jié)構(gòu),轉(zhuǎn)為數(shù)組。也就是說(shuō),只要某個(gè)數(shù)據(jù)結(jié)構(gòu)部署了 Iterator 接口,就可以對(duì)它使用擴(kuò)展運(yùn)算符,將其轉(zhuǎn)為數(shù)組。
由于數(shù)組的遍歷會(huì)調(diào)用遍歷器接口,所以任何接受數(shù)組作為參數(shù)的場(chǎng)合,其實(shí)都調(diào)用了遍歷器接口。下面是一些例子。
for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()(比如new Map([["a",1],["b",2]]))
Promise.all()
Promise.race()
for...offor...of 循環(huán)是最新添加到 JavaScript 循環(huán)系列中的循環(huán)。
它結(jié)合了其兄弟循環(huán)形式 for 循環(huán)和 for...in 循環(huán)的優(yōu)勢(shì),可以循環(huán)任何可迭代(也就是遵守可迭代協(xié)議)類型的數(shù)據(jù)。默認(rèn)情況下,包含以下數(shù)據(jù)類型:String、Array、Map 和 Set,注意不包含 Object 數(shù)據(jù)類型(即 {})。默認(rèn)情況下,對(duì)象不可迭代。
在研究 for...of 循環(huán)之前,先快速了解下其他 for 循環(huán),看看它們有哪些不足之處。
for 循環(huán)for 循環(huán)的最大缺點(diǎn)是需要跟蹤計(jì)數(shù)器和退出條件。我們使用變量 i 作為計(jì)數(shù)器來(lái)跟蹤循環(huán)并訪問數(shù)組中的值。我們還使用 Array.length 來(lái)判斷循環(huán)的退出條件。
雖然 for 循環(huán)在循環(huán)數(shù)組時(shí)的確具有優(yōu)勢(shì),但是某些數(shù)據(jù)結(jié)構(gòu)不是數(shù)組,因此并非始終適合使用 loop 循環(huán)。
for...in 循環(huán)for...in 循環(huán)改善了 for 循環(huán)的不足之處,它消除了計(jì)數(shù)器邏輯和退出條件。但是依然需要使用 index 來(lái)訪問數(shù)組的值.
此外,當(dāng)你需要向數(shù)組中添加額外的方法(或另一個(gè)對(duì)象)時(shí),for...in 循環(huán)會(huì)帶來(lái)很大的麻煩。因?yàn)?for...in 循環(huán)循環(huán)訪問所有可枚舉的屬性,意味著如果向數(shù)組的原型中添加任何其他屬性,這些屬性也會(huì)出現(xiàn)在循環(huán)中。這就是為何在循環(huán)訪問數(shù)組時(shí),不建議使用 for...in 循環(huán)。
注意: forEach 循環(huán) 是另一種形式的 JavaScript 循環(huán)。但是,forEach() 實(shí)際上是數(shù)組方法,因此只能用在數(shù)組中。也無(wú)法停止或退出 forEach 循環(huán)。如果希望你的循環(huán)中出現(xiàn)這種行為,則需要使用基本的 for 循環(huán)。for...of 循環(huán)
for...of 循環(huán)用于循環(huán)訪問任何可迭代的數(shù)據(jù)類型。
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const digit of digits) { console.log(digit); }
可以隨時(shí)停止或退出 for...of 循環(huán)。
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const digit of digits) { if (digit % 2 === 0) { continue; } console.log(digit); //1,3,5,7,9 }
不用擔(dān)心向?qū)ο笾刑砑有碌膶傩浴or...of 循環(huán)將只循環(huán)訪問對(duì)象中的值。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92312.html
摘要:迭代器模式迭代器模式是指提供一種方法順序訪問一個(gè)聚合對(duì)象中的各個(gè)元素,而不需要暴露該對(duì)象的內(nèi)部表示。可迭代協(xié)議和迭代器協(xié)議。生成器函數(shù)是可以作為迭代器工廠的函數(shù),當(dāng)它被執(zhí)行時(shí)會(huì)返回一個(gè)新的對(duì)象,該對(duì)象符合可迭代協(xié)議和迭代器協(xié)議。 迭代器模式 迭代器模式是指提供一種方法順序訪問一個(gè)聚合對(duì)象中的各個(gè)元素,而不需要暴露該對(duì)象的內(nèi)部表示。 迭代器分為內(nèi)部迭代器和外部迭代器。內(nèi)部迭代器只需一次初...
摘要:基本原理解構(gòu)是提供的語(yǔ)法糖,其實(shí)內(nèi)在是針對(duì)可迭代對(duì)象的接口,通過遍歷器按順序獲取對(duì)應(yīng)的值進(jìn)行賦值。屬性值返回一個(gè)對(duì)象的無(wú)參函數(shù),被返回對(duì)象符合迭代器協(xié)議。迭代器協(xié)議定義了標(biāo)準(zhǔn)的方式來(lái)產(chǎn)生一個(gè)有限或無(wú)限序列值。 更多系列文章請(qǐng)看 1、基本語(yǔ)法 1.1、數(shù)組 // 基礎(chǔ)類型解構(gòu) let [a, b, c] = [1, 2, 3] console.log(a, b, c) // 1, 2, ...
摘要:本文從使用對(duì)數(shù)組進(jìn)行遍歷開始說(shuō)起,粗略對(duì)比使用進(jìn)行遍歷的差異,并由此引入中可迭代對(duì)象迭代器的概念,并對(duì)其進(jìn)行粗略介紹。說(shuō)到這里,就繼續(xù)說(shuō)一下迭代器關(guān)閉的情況了。確實(shí),符合可迭代協(xié)議和迭代器協(xié)議的。 本文從使用 forEach 對(duì)數(shù)組進(jìn)行遍歷開始說(shuō)起,粗略對(duì)比使用 forEach , for...in , for...of 進(jìn)行遍歷的差異,并由此引入 ES6 中 可迭代對(duì)象/迭代器 的概...
摘要:需要說(shuō)明的是,每次執(zhí)行完函數(shù)之后,都會(huì)返回一個(gè)對(duì)象這個(gè)返回值有兩個(gè)屬性和,對(duì)象通過這個(gè)返回值來(lái)告訴外界函數(shù)的執(zhí)行情況。函數(shù)的返回值變成這樣可以發(fā)現(xiàn)的值變?yōu)榱耍驗(yàn)楹瘮?shù)已經(jīng)執(zhí)行完了。在規(guī)范中,新增了兩個(gè)協(xié)議可迭代協(xié)議和迭代器協(xié)議。 Koa是最近比較火的一款基于Node的web開發(fā)框架。說(shuō)他是一個(gè)框架,其實(shí)他更像是一個(gè)函數(shù)庫(kù),通過某種思想(或者說(shuō)某種約定),將眾多的中間件聯(lián)系在一起,從而提...
摘要:理解迭代對(duì)象迭代器生成器后端掘金本文源自作者的一篇博文,原文是,俺寫的這篇文章是按照自己的理解做的參考翻譯。比較的是兩個(gè)對(duì)象的內(nèi)容是后端掘金黑魔法之協(xié)程異步后端掘金本文為作者原創(chuàng),轉(zhuǎn)載請(qǐng)先與作者聯(lián)系。 完全理解關(guān)鍵字with與上下文管理器 - 掘金如果你有閱讀源碼的習(xí)慣,可能會(huì)看到一些優(yōu)秀的代碼經(jīng)常出現(xiàn)帶有 with 關(guān)鍵字的語(yǔ)句,它通常用在什么場(chǎng)景呢?今天就來(lái)說(shuō)說(shuō) with 和 上下...
閱讀 982·2023-04-26 01:47
閱讀 1672·2021-11-18 13:19
閱讀 2042·2019-08-30 15:44
閱讀 645·2019-08-30 15:44
閱讀 2291·2019-08-30 15:44
閱讀 1232·2019-08-30 14:06
閱讀 1420·2019-08-30 12:59
閱讀 1900·2019-08-29 12:49