學(xué)會javascript之迭代器
簡介
迭代器是一種設(shè)計模式,可在容器對象 如 鏈表、數(shù)組上遍歷,無需關(guān)心容器對象的內(nèi)存分配的實現(xiàn)細節(jié)。簡單的理解就是可以一個一個的依次拿到其中的數(shù)據(jù),類似一個移動的指針,但是會告訴我們什么時候結(jié)束。這樣我們可以拿到數(shù)據(jù)之后可以做一些我們需要做的事情。
js 中的迭代器是什么樣子的
在javascript 中迭代器是一個特殊對象,這個迭代器對象有一個next()方法,每次調(diào)用都返回一個對象(結(jié)果對象)。結(jié)果對象有兩個屬性:一個是value,表示下一個將要返回的值;另一個是done,它是一個布爾類型的值,如果已經(jīng)迭代到序列中的最后一個值,則它為 true。迭代器還會保存一個內(nèi)部指針,用來指向當(dāng)前集合中值的位置,每調(diào)用一次next()方法,都會返回下一個可用的值,類似下面這個對象的結(jié)構(gòu)。
{ next: function () { return { value:'', done: true / false } } }
迭代協(xié)議
隨著javascript 語言的能力進一步提升,新增了一些新的數(shù)據(jù)類型 如 Map、Set、WeakMap 等,為了這些不同的數(shù)據(jù)結(jié)構(gòu),可以統(tǒng)一的迭代,es6 增加了迭代協(xié)議這個東西。
迭代協(xié)議并不是新的內(nèi)置實現(xiàn)或語法,而是協(xié)議。這些協(xié)議可以被任何遵循某些約定的對象來實現(xiàn)。
迭代協(xié)議具體分為兩個協(xié)議:可迭代協(xié)議和迭代器協(xié)議。
簡單的理解就是在js 中任何對象只要滿足迭代協(xié)議就可以遍歷
可迭代協(xié)議
要成為可迭代對象, 一個對象必須實現(xiàn) @@iterator 方法。這意味著對象(或者它原型鏈上的某個對象)必須有一個鍵為 @@iterator 的屬性,可通過常量 Symbol.iterator 訪問該屬性:
簡單的理解,你想讓一個東西可以遍歷,那么這個東西要有一個 @@iterator ,這個屬性可以通過Symbol.iterator 訪問
屬性 |
值 |
[Symbol.iterator] |
一個無參數(shù)的函數(shù),其返回值為一個符合迭代器協(xié)議的對象。 |
迭代器協(xié)議
迭代器協(xié)議定義了產(chǎn)生一系列值(無論是有限個還是無限個)的標(biāo)準(zhǔn)方式。當(dāng)值為有限個時,所有的值都被迭代完畢后,則會返回一個默認返回值。
只有實現(xiàn)了一個擁有以下語義(semantic)的 next() 方法,一個對象才符合迭代器協(xié)議:
屬性 |
值 |
next |
一個無參數(shù)函數(shù),返回一個應(yīng)當(dāng)擁有以下兩個屬性的對象: done(boolean) next() 方法必須返回一個對象,該對象應(yīng)當(dāng)有兩個屬性: done 和 value,如果返回了一個非對象值(比如 false 或 undefined),則會拋出一個 異常("iterator.next() returned a non-object value")。 |
迭代過程
當(dāng)一個對象需要被迭代的時候(比如被寫入一個 for...of 循環(huán)時),首先,會不帶參數(shù)調(diào)用它的 @@iterator 方法( 此時返回的是結(jié)構(gòu)是這樣的 { next: function () {}}),然后使用此方法返回的迭代器獲得要迭代的值(其實就是不斷的調(diào)用這個next()方法)
迭代總結(jié)
迭代協(xié)議可以總結(jié)為,一個東西要遍歷,必須滿足可迭代協(xié)議跟迭代器協(xié)議
- 可迭代協(xié)議:這個對象必須有@@iterator,可以通過Symbol.iterator 訪問
- 迭代器協(xié)議:是一個對象,這個對象的next() 函數(shù)返回一個對象,這個對象包括兩個屬性,一個是value,一個是done(boolean,是否是最后一個元素,done 為 true 時 value 可省略)
也就是說 迭代器對象本質(zhì)上,就是一個指針對象。通過指針對象的next(),用來移動指針。
自定義迭代
對象是沒有實現(xiàn)迭代器,所以不能遍歷對象,為了可以實現(xiàn)對象的遍歷,我們需要在對象上實現(xiàn)上面說的迭代器,通常有兩種寫法,一種是傳統(tǒng)的寫法,這種需要自己去控制內(nèi)部的狀態(tài),另外一種是利用生成器函數(shù)返回的Generator的迭代器來實現(xiàn),代碼如下:
傳統(tǒng)寫法
let obj = { name: 'joel', adress: 'gz', [Symbol.iterator]: () => { // 這里不要用this, 因為是return fn, this 會丟失 let index = -1, atrrList = Object.keys(obj); const objIterator = { next: () => { let result = '' index++ if (index < atrrList.length) { result = { value: atrrList[index], done: false } } else { result = { done: true } } return result } } return objIterator } } for (const item of obj) { console.log('atrrs:' + item + ',value:' + obj[item]) }
生成器函數(shù)寫法
// 為不可迭代的對象添加迭代器 let obj = { a: 1, b: 2 } obj[Symbol.iterator] = function* () { let keys = Object.keys(obj); //取到key值的長度 let len = keys.length; //定義循環(huán)變量 let n = 0; //條件判斷 while (n <= len - 1) { yield { k: keys[n], v: obj[keys[n]] }; n++ } } //返回的是個對象的key和value for (let { k, v } of obj) { console.log(k, v); }
其他相關(guān)如內(nèi)置可迭代對象、用于可迭代對象的語法、接受可迭代對象的內(nèi)置api 等 請點擊 這里
到此這篇關(guān)于學(xué)會javascript之迭代器的文章就介紹到這了,更多相關(guān)javascript 迭代器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
從JQuery源碼分析JavaScript函數(shù)的apply方法與call方法
這篇文章主要介紹了從JQuery源碼分析JavaScript函數(shù)的apply方法與call方法,本文結(jié)合JQuery源碼和js高級程序設(shè)計再次探究apply方法與call方法,需要的朋友可以參考下2014-09-09一個頁面元素appendchild追加到另一個頁面元素的問題
一般都是自己創(chuàng)建元素然后append到頁面的但是如果是頁面本身有的元素append到另一個頁面元素呢,很多的新手朋友對此問題比較好奇,本人也是如此啊,好了不多說,切入主題,感興趣的朋友可以了解下哦2013-01-01JS中判斷字符串中出現(xiàn)次數(shù)最多的字符及出現(xiàn)的次數(shù)的簡單實例
下面小編就為大家?guī)硪黄狫S中判斷字符串中出現(xiàn)次數(shù)最多的字符及出現(xiàn)的次數(shù)的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06