ES6 Iterator遍歷器原理,應(yīng)用場(chǎng)景及相關(guān)常用知識(shí)拓展詳解
本文實(shí)例講述了ES6 Iterator遍歷器原理,應(yīng)用場(chǎng)景及相關(guān)常用知識(shí)拓展。分享給大家供大家參考,具體如下:
介紹Iterator之前先列舉下js的表示數(shù)據(jù)集合結(jié)構(gòu)的幾種方式:
在es6之前有 Array , Object, es6新增了 map, set,當(dāng)然用戶也可以組合使用這幾種數(shù)據(jù)結(jié)構(gòu),靈活存儲(chǔ)數(shù)據(jù)。
但是當(dāng)數(shù)據(jù)結(jié)構(gòu)變得復(fù)雜后,怎樣取到里面的數(shù)據(jù)就也相對(duì)復(fù)雜,這就需要有一種讀取數(shù)據(jù)的統(tǒng)一的接口機(jī)制,來(lái)處理不同的數(shù)據(jù)結(jié)構(gòu)。
遍歷器就是這樣一種接口機(jī)制,Iterator是一種接口,為不同數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的接口機(jī)制。
相應(yīng)的任何數(shù)據(jù)結(jié)構(gòu)只要部署Iterator接口,就可以完成遍歷操作。
Iterator的作用:
1,為各種數(shù)據(jù)結(jié)構(gòu)提供一種統(tǒng)一的,簡(jiǎn)單的訪問(wèn)接口;
2,使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按照某種次序排列;
3,ES6提供了一種新的遍歷循環(huán)(for......of.....),Iterator被for......of.....循環(huán)調(diào)用;
Iterator本質(zhì):
遍歷器本質(zhì)上是一種指針對(duì)象,指針對(duì)象上有next()方法,第幾次調(diào)用就指向第幾個(gè)成員
Iterator上next()方法調(diào)用返回:
1,返回當(dāng)前成員的信息
2,返回遍歷是否結(jié)束
模擬實(shí)現(xiàn)Iterator
var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; } }; }
使用Typescript
interface Iterable { [Symbol.iterator]() : Iterator, } interface Iterator { next(value?: any) : IterationResult, } interface IterationResult { value: any, done: boolean, }
關(guān)于默認(rèn)的Iterator接口:
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的本質(zhì):
1,Symbol.iterator本身是一個(gè)函數(shù),對(duì)應(yīng)當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的遍歷器生成函數(shù);
2,執(zhí)行Symbol.iterator這個(gè)函數(shù)會(huì)返回一個(gè)遍歷器。
實(shí)例:
const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; } }; } }; //這樣定義后對(duì)象就有了Iterator接口 //執(zhí)行對(duì)象obj的symbol.iterator后,返回一個(gè)遍歷器
具有原生iterator的數(shù)據(jù)結(jié)構(gòu):
Array , Map, Set, String, TypedArray, 函數(shù)的argulements對(duì)象,NodeList對(duì)象(節(jié)點(diǎn)對(duì)象);
數(shù)組iterator實(shí)例
let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next() // { value: undefined, done: true }
對(duì)象iterator接口實(shí)現(xiàn)
class RangeIterator { constructor(start, stop) { this.value = start; this.stop = stop; } [Symbol.iterator]() { return this; } next() { var value = this.value; if (value < this.stop) { this.value++; return {done: false, value: value}; } return {done: true, value: undefined}; } } function range(start, stop) { return new RangeIterator(start, stop); } for (var value of range(0, 3)) { console.log(value); // 0, 1, 2 }
注意:如果一個(gè)對(duì)象沒(méi)有iterator接口,而其原型鏈上有Iterator接口,也可以通過(guò)繼承而擁有該接口;
使用while
循環(huán)遍歷
var $iterator = ITERABLE[Symbol.iterator](); var $result = $iterator.next(); while (!$result.done) { var x = $result.value; // ... $result = $iterator.next(); }
基本概念基本就是這些,接下來(lái)看下使用場(chǎng)景
Iterator的使用場(chǎng)景:
默認(rèn)調(diào)用場(chǎng)景:
for....of...循環(huán), 解構(gòu)賦值, 擴(kuò)展運(yùn)算符, yield*關(guān)鍵字
ES6 借鑒 C++、Java、C# 和 Python 語(yǔ)言,引入了for...of
循環(huán),作為遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一的方法
這里主要介紹下yield*,其余幾個(gè)都比較好理解
yield*
后面跟的是一個(gè)可遍歷的結(jié)構(gòu),它會(huì)調(diào)用該結(jié)構(gòu)的遍歷器接口
let generator = function* () { yield 1; yield* [2,3,4];//執(zhí)行時(shí)默認(rèn)遍歷數(shù)組 yield 5; }; var iterator = generator(); iterator.next() // { value: 1, done: false } iterator.next() // { value: 2, done: false } iterator.next() // { value: 3, done: false } iterator.next() // { value: 4, done: false } iterator.next() // { value: 5, done: false } iterator.next() // { value: undefined, done: true }
其他場(chǎng)景:
由于數(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()
知識(shí)拓展:
遍歷器對(duì)象的 return(),throw()
return方法在循環(huán)退出或者報(bào)錯(cuò)時(shí)調(diào)用
throw
方法主要是配合 Generator 函數(shù)使用(詳見(jiàn)generator)
計(jì)算生成的數(shù)據(jù)結(jié)構(gòu)
在原有數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)上計(jì)算生成的數(shù)據(jù)結(jié)構(gòu),例如Object,Map,Set,Array的entries(),keys(), value()方法生成的數(shù)據(jù)結(jié)構(gòu),默認(rèn)具有iterator接口
類似數(shù)組對(duì)象
常見(jiàn):字符串,NodeList節(jié)點(diǎn)對(duì)象,參數(shù)arguments
1,并不是所有類似數(shù)組的對(duì)象都具有 Iterator 接口
2,對(duì)于類數(shù)組對(duì)象可以通過(guò)Array.From()將類數(shù)組對(duì)象轉(zhuǎn)化為數(shù)組對(duì)象
3,for-of可以識(shí)別32 位 UTF-16 字符
for (let x of 'a\uD83D\uDC0A') { console.log(x); }
for-of和其他遍歷方法對(duì)比:
for循環(huán),forEach循環(huán),for...in...循環(huán)
forEach循環(huán)無(wú)法中途跳出
for...in
循環(huán)有幾個(gè)缺點(diǎn)(for...in
循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的,不適用于遍歷數(shù)組),
- 數(shù)組的鍵名是數(shù)字,但是
for...in
循環(huán)是以字符串作為鍵名“0”、“1”、“2”等等。 for...in
循環(huán)不僅遍歷數(shù)字鍵名,還會(huì)遍歷手動(dòng)添加的其他鍵,甚至包括原型鏈上的鍵。- 某些情況下,
for...in
循環(huán)會(huì)以任意順序遍歷鍵名。
對(duì)于for...of...
- 有著同
for...in
一樣的簡(jiǎn)潔語(yǔ)法,但是沒(méi)有for...in
那些缺點(diǎn)。 - 不同于
forEach
方法,它可以與break
、continue
和return
配合使用。 - 提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口。
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。
更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
微信小程序wx.getImageInfo()如何獲取圖片信息
這篇文章主要為大家詳細(xì)介紹了微信小程序wx.getImageInfo()如何獲取圖片信息,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01JS學(xué)習(xí)筆記之?dāng)?shù)組去重實(shí)現(xiàn)方法小結(jié)
這篇文章主要介紹了JS學(xué)習(xí)筆記之?dāng)?shù)組去重實(shí)現(xiàn)方法,結(jié)合實(shí)例形式總結(jié)分析了javascript數(shù)組去重的5種常見(jiàn)實(shí)現(xiàn)方法及相關(guān)操作技巧,需要的朋友可以參考下2019-05-05前端高頻面試題之JS中堆和棧的區(qū)別和瀏覽器的垃圾回收機(jī)制
本文給大家分享前端高頻面試題JS中堆和棧的區(qū)別和瀏覽器的垃圾回收機(jī)制,本文分文別類給大家介紹了棧(stack)和堆(heap)的區(qū)別基本類型和引用類型的相關(guān)知識(shí),瀏覽器垃圾回收機(jī)制包括基本概念給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10JavaScript庫(kù)urlcat?之URL構(gòu)建器庫(kù)
這篇文章主要介紹了JavaScript庫(kù)urlcat之URL構(gòu)建器庫(kù),urlcat?是一個(gè)小型的JavaScript庫(kù),使構(gòu)建URL非常方便并防止常見(jiàn)錯(cuò)誤。下文來(lái)看對(duì)其詳細(xì)介紹吧,需要的小伙伴可以參考一下2022-02-02微信小程序?qū)Ш綑诨瑒?dòng)定位功能示例(實(shí)現(xiàn)CSS3的positionsticky效果)
這篇文章主要介紹了微信小程序?qū)Ш綑诨瑒?dòng)定位功能,可實(shí)現(xiàn)CSS3的positionsticky效果,涉及微信小程序事件監(jiān)聽(tīng)、狀態(tài)判斷及屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01