摘要:迭代器模式迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而不需要暴露該對象的內部表示。可迭代協議和迭代器協議。生成器函數是可以作為迭代器工廠的函數,當它被執行時會返回一個新的對象,該對象符合可迭代協議和迭代器協議。
迭代器模式
迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而不需要暴露該對象的內部表示。
迭代器分為內部迭代器和外部迭代器。內部迭代器只需一次初始調用,而外部迭代器必須顯式地請求迭代下一個元素,這樣我們就可以手動控制迭代過程。
實現一個內部迭代器:
Array.prototype.innerIterator = function(callback){ for (let i = 0, len = this.length; i < len; i++) { callback && callback.call(this[i], this[i], i) } }; [1,2,3].innerIterator(function(item, index){ console.log("item:", item, "index:", index) }) // item: 1 index: 0 // item: 2 index: 1 // item: 3 index: 2
實現一個外部迭代器:
Array.prototype.outerInterator = function(){ let index = 0; return { next: () => { return index < this.length ? {value: this[index++], done: false}: {value: undefined, done: true} } } } let iterator = [1,2,3].outerInterator(); for(let next; (next = iterator.next()) && !next.done;) { console.log("item", next.value) } // item 1 // item 2 // item 3迭代協議
了解了迭代器模式,再來看看 ES6 中補充的迭代協議。可迭代(iterable)協議和迭代器(iterator)協議。
可迭代協議:
一個可迭代對象(或其原型上),必須有一個 Symbol.iterator 的屬性,該屬性所對應的值為返回一個對象的無參函數,被返回對象符合迭代器協議。當可迭代對象需要迭代時,調用該方法。
一些數據類型內置了 @@iterator 方法,有自己默認的迭代行為。(String, Array, TypedArray, Map , Set 等都是內置可迭代對象, 因為它們的原型對象都有一個 @@iterator 方法.)([Symbol.iterator]、@@iterator 可以認為是一回事)
let iterator = ("hi")[Symbol.iterator]() var a = iterator.next(); // a { value: "h", done: false }
迭代器協議:
一個迭代器必須實現了 next() 方法,該方法是返回一個對象的無參函數。被返回的對象有兩個必要的屬性:done 和 value。
Array.prototype.Iteration = function(){ let index = 0; return { [Symbol.iterator](){return this}, next: () => { return index < this.length ? {value: this[index++], done: false}: {value: undefined, done: true} } } }; let Iteration = [2, 3, 4].Iteration(); for(let value of Iteration) { console.log("value", value) } // value 2 // value 3 // value 4
不能發現,Iteration 同時滿足可迭代協議和迭代協議。又因為是可迭代的,for...of 是可以直接使用,而且這個和外部迭代器十分相似。
一旦一種數據結構有了 @@iterator 方法后, 就認為是可迭代的。ES6 中許多新的方法就是基于此的 解構賦值、擴展運算符、yield*,還有 for..of、Array.from()等。
知道了以上知識,也就知道了為什么對象不可以直接使用 for...of 了。不過我們可以在對象原型上添加 @@iterator 方法,使之成為可迭代的。
Object.prototype.Iteration = function(){ let keys = Object.keys(this), index = 0; return{ [Symbol.iterator](){return this}, next: () => { let current = index++; return current < keys.length? {value: [keys[current], this[keys[current]]], done: false}: {value: undefined, done: true}; } } } let iterator = {"a": 1, "b": 2, "c": 3}.Iteration(); for(let [key, value] of iterator) { console.log("key:", key, "value:", value) } // key: a value: 1 // key: b value: 2 // key: c value: 3生成器
像以上的的對象都是我們自己手動實現的,符合可迭代協議和迭代協議的對象。看起來很麻煩,還好這些工作已經有函數替我們做了,那就是生成器函數。
生成器函數是可以作為迭代器工廠的函數,當它被執行時會返回一個新的 Generator 對象,該對象符合可迭代協議和迭代器協議。
現在我們用生成器函數使得對象符合迭代協議:
Object.prototype.Iteration = function *(){ for(let [key, value] of Object.entries(this)){ yield [key, value] } } for(let [key, value] of {"a": 1, "b": 2, "c": 3}.Iteration()) { console.log("key:", key, "value:", value) } // key: a value: 1 // key: b value: 2 // key: c value: 3
在這里生成器只是作為迭代器而已,其實它還是消息雙向傳遞系統。也正是這些特性的存在,使得異步流程控制又向前邁了一大步。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102756.html
摘要:上一篇文章標準庫內置類型數字類型下一篇文章標準庫內置類型文本序列類型迭代器類型支持在容器中進行迭代的概念。該對象需要支持下文所述的迭代器協議。這是同時允許容器和迭代器配合和語句使用所必須的。 上一篇文章:Python標準庫---10、內置類型:數字類型下一篇文章:Python標準庫---12、內置類型:文本序列類型(str) ## 迭代器類型Python 支持在容器中進行迭代的概念。...
摘要:示例代碼如下此示例中可以看出,當迭代器終止時,通過拋出異常告知迭代器已耗盡。但如果迭代器所指向的數據結構在其存在時發生了插入或刪除操作,則迭代器將可能失效。與的情形類似,對進行任何插入操作也將損壞迭代器。 花下貓語:之前說過,我對于編程語言跟其它學科的融合非常感興趣,但我還說漏了一點,就是我對于 Python 跟其它編程語言的對比學習,也很感興趣。所以,我一直希望能聚集一些有其它語言基...
摘要:本文重點掌握可迭代的對象的定義掌握可迭代對象迭代器與生成器之間的關系和異同熟悉標準庫中生成器。二迭代器迭代器介紹迭代器用于從集合中取出元素的對象。若想再次迭代須重建迭代器。迭代器檢查方式調用,。區別可迭代的對象不是迭代器。 導語:本文章記錄了本人在學習Python基礎之控制流程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。 本文重點: 1、掌握可迭代的對象的...
摘要:本文從使用對數組進行遍歷開始說起,粗略對比使用進行遍歷的差異,并由此引入中可迭代對象迭代器的概念,并對其進行粗略介紹。說到這里,就繼續說一下迭代器關閉的情況了。確實,符合可迭代協議和迭代器協議的。 本文從使用 forEach 對數組進行遍歷開始說起,粗略對比使用 forEach , for...in , for...of 進行遍歷的差異,并由此引入 ES6 中 可迭代對象/迭代器 的概...
閱讀 1310·2021-11-16 11:45
閱讀 2233·2021-11-02 14:40
閱讀 3872·2021-09-24 10:25
閱讀 3029·2019-08-30 12:45
閱讀 1255·2019-08-29 18:39
閱讀 2468·2019-08-29 12:32
閱讀 1588·2019-08-26 10:45
閱讀 1917·2019-08-23 17:01