摘要:一個對象如果要有可被循環調用的接口,就必須在的屬性上部署遍歷器生成方法原型鏈上的對象具有該方法也可。阮大神案例上面代碼是一個類部署接口的寫法。屬性對應一個函數,執行后返回當前對象的遍歷器對象。
最近看阮一峰阮大神的ES6,剛剛看到Iterator和for...of循環這一章,小作筆記跟大家略微分享一下,不足之處還望大家多多指正
Iterator(遍歷器)就是一種機制;任何數據結構只要是部署了iterator接口,就可以完成遍歷操作(即依次處理該數據的所有成員);
Iterator的作用有三個:一是為各種數據結構,提供一個統一的、簡便的訪問接口;二是使得數據結構的成員能夠按某種次序排列;三是ES6創造了一種新的遍歷命令for...of循環,Iterator接口主要供for...of消費。(阮大神原話);
只要是一個對象部署了Symbol.interator接口,就可以用for...of遍歷該對象,同時也可以調用該接口的Symbol.interator方法調用next()方法對對象進行遍歷,不同的是for..of是對該對象的值的輸出,而next()返回的是對象。
例如下面的例子:
如果調用next方法就是
調用next()方法會返回一個對象{value:value;done:true or false};直到對遍歷對象的值便利完成之后,next()方法會返回一個{value:undefined; done:true}代表已經遍歷完成,再調用next()方法也不會報錯但是依舊會返回{value:undefined; done:true};
有一些對象是原生就封裝好的Symbol.iterator接口,可以直接調用,當然也可以直接用for...of遍歷;
在ES6中,有三類數據結構原生具備Iterator接口:數組、某些類似數組的對象、Set和Map結構。
如果沒有原生的Symbol.iterator接口,想用for...of遍歷,就需要自己在該對象中部署Symbol.iterator接口,例如
一個對象如果要有可被for...of循環調用的Iterator接口,就必須在Symbol.iterator的屬性上部署遍歷器生成方法(原型鏈上的對象具有該方法也可)。
一個對象如果要有可被for...of循環調用的Iterator接口,就必須在Symbol.iterator的屬性上部署遍歷器生成方法(原型鏈上的對象具有該方法也可)。 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}; } else { return {done: true, value: undefined}; } } } function range(start, stop) { return new RangeIterator(start, stop); } for (var value of range(0, 3)) { console.log(value); }//阮大神案例
上面代碼是一個類部署Iterator接口的寫法。Symbol.iterator屬性對應一個函數,執行后返回當前對象的遍歷器對象。
原型鏈上部署Symbol.iterator接口
function Obj(value){ this.value = value; this.next = null; } Obj.prototype[Symbol.iterator] = function(){ var iterator = { next: next }; var current = this; function next(){ if (current){ var value = current.value; var done = current == null; current = current.next; return { done: done, value: value } } else { return { done: true } } } return iterator; } var one = new Obj(1); var two = new Obj(2); var three = new Obj(3); one.next = two; two.next = three; for (var i of one){ console.log(i) } // 1 // 2 // 3
對象內部部署
let obj = { data: [ "hello", "world" ], [Symbol.iterator]() { const self = this; let index = 0; return { next() { if (index < self.data.length) { return { value: self.data[index++], done: false }; } else { return { value: undefined, done: true }; } } }; } };
也就是說如果一個對象沒有Symbol.iterator接口,可以在類本身上面部署,也可以在原型連上部署,也可以在對象內部部署
對于類似數組的對象(存在數值鍵名和length屬性),部署Iterator接口,有一個簡便方法,就是Symbol.iterator方法直接引用數組的Iterator接口。
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; // 或者 NodeList.prototype[Symbol.iterator] = [][Symbol.iterator]; [...document.querySelectorAll("div")] // 可以執行了
具體請看例子
let iterable = { 0: "a", 1: "b", 2: "c", length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // "a", "b", "c" }
**但是請記住,這個方法僅僅適用于類數組對象,上面的也可以直接用Array.from(iterable)轉換成數組來遍歷,例如
let arrayLike = { length: 2, 0: "a", 1: "b" }; for (let x of Array.from(arrayLike)) { console.log(x); }//a b
對于普通對象這兩個方法是不管用的,**例如
let iterable = { edition: "a", writer: "b", read: "c", length: 3, }; for (let item of Array.from(iterable)) { console.log(item); }
上面的代碼就會輸出三個undefined
let iterable = { edition: "a", writer: "b", read: "c", length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); //報錯 }
上面的代碼就會拋異常的;
其實ES6很多地方都用的到Iterator這個接口,例如:
解構賦值
擴展運算符
yield*
最后需要說下,字符串既是類數組對象同時自己也有原生Symbol.iterator接口可以直接調用,例如
var str = "hell";
for(let v of str){
console.log(v);//"h","e","l","l"
}
對于字符串來說,for...of循環還有一個特點,就是會正確識別32位UTF-16字符。
for...of 區別于for循環,for循環比較麻煩,但是是最原始的方法;
for...of 區別于數組的forEach方法,因為forEach方法是從頭到尾執行,不會跳出,但是遇到break或者return,continue會跳出循環
有著同for...in一樣的簡潔語法,但是沒有for...in那些缺點。
不同用于forEach方法,它可以與break、continue和return配合使用。
提供了遍歷所有數據結構的統一操作接口。
更詳細的請查看阮大神(http://es6.ruanyifeng.com/#docs/iterator)本章內容
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86086.html
摘要:本文從使用對數組進行遍歷開始說起,粗略對比使用進行遍歷的差異,并由此引入中可迭代對象迭代器的概念,并對其進行粗略介紹。說到這里,就繼續說一下迭代器關閉的情況了。確實,符合可迭代協議和迭代器協議的。 本文從使用 forEach 對數組進行遍歷開始說起,粗略對比使用 forEach , for...in , for...of 進行遍歷的差異,并由此引入 ES6 中 可迭代對象/迭代器 的概...
摘要:語法參數當前遍歷項。遍歷的范圍在第一次調用前就會確定。已刪除的項不會被遍歷到。的是由提出的,目的是作為遍歷所有數據結構的統一方法。不僅可以遍歷數組,還可以遍歷結構,某些類似數組的對象如對象對象,對象,以及字符串。 即使是最簡單的循環,其中也深藏學問 ECMAScript5(es5)有三種for循環 簡單for for in forEach ECMAScript6(es6)新增 fo...
摘要:中可以實現遍歷的數據類型主要是對象,其中包括普通對象與數組。遍歷器是一種接口,為各種不同的數據結構提供統一的訪問機制。實例五遍歷器對象實例五是的遍歷過程,通過手動調用其對象的方法實現信息獲取。為每個數組元素執行函數。 前言 ??將依據自身痛點學習,計劃對原生JavaScript寫一個系統,本文為第一篇,感興趣的同學可以關注個人公眾號:ZeroToOneMe,或者github博客,將持續...
摘要:有兩個協議可迭代協議和迭代器協議。為了變成可迭代對象,一個對象必須實現或者它原型鏈的某個對象必須有一個名字是的屬性迭代器協議該迭代器協議定義了一種標準的方式來產生一個有限或無限序列的值。 ECMAScript 2015的幾個補充,并不是新的內置或語法,而是協議。這些協議可以被任何遵循某些約定的對象來實現。有兩個協議:可迭代協議和迭代器協議。 可迭代協議 可迭代協議允許 JavaScri...
摘要:我關注的賀老賀師俊前輩最近發表個這樣一條微博雖然這條微博沒有引起大范圍的關注和討論,但是作為新人,我陷入了思考。通過賀老的微博,對一個問題進行探究,最終找到核心成員的一文,進行參考并翻譯。 我關注的賀老—賀師俊前輩@johnhax 最近發表個這樣一條微博: showImg(https://segmentfault.com/img/remote/1460000010452807); 雖然...
閱讀 2672·2021-11-18 10:02
閱讀 3402·2021-09-28 09:35
閱讀 2586·2021-09-22 15:12
閱讀 741·2021-09-22 15:08
閱讀 3071·2021-09-07 09:58
閱讀 3464·2021-08-23 09:42
閱讀 725·2019-08-30 12:53
閱讀 2072·2019-08-29 13:51