爲各類不一樣的數據結構提供統一的訪問機制!主要是爲了使用for...of方法javascript
JavaScript原有的表示'集合'的數據結構,主要是數組和對象。ES6又添加了Set和Map。這樣就須要一種統一的接口機制, 來處理全部不一樣的數據結構。java
遍歷器就是這樣一種機制,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署了Iterator接口,就能夠完成遍歷操做。數組
說白了,每次調用返回的就是一個對象,裏面包括value和done兩個屬性。value屬性是當前成員的值,done屬性是一個布爾值,表示遍歷是否結束。數據結構
說了這麼多,拿出個具體的例子🌰解釋一下咯 。async
var it = makeIterator(['a','b']);
function makeIterator(array) {
var nextIndex = 0;
return {
next:function() {
nextIndex < array.length ?
{value: array[nextIndex++], done: false }:
{value: undefined, done: true}
}
}
}
it.next();
it.next();
複製代碼
上面的代碼定義了一個makeIterator函數,他是一個遍歷器生成函數,做用就是返回一個遍歷器對象。對數組['a','b']執行這個函數,就會返回該數組的遍歷器對象(即指針對象)it。函數
指針對象的next方法,用來移動指針。
next方法返回一個對象,表示數據成員的信息。ui
總之,調用指針對象的next方法,就能夠遍歷事先給定的數據結構。this
Iteratot接口的目的,就是爲全部的數據結構,提供了一種統一的訪問機制,即for...of循環。當使用for...of循環遍歷某種數據結構時,該循環會自動去尋找 Iterator 接口spa
說白了,我理解的Iterator接口的產生,就是爲了使用for...of!指針
一種數據結構,只要部署了Iterator接口,就是可遍歷的,就能用for...of。
ES6規定,默認的Iterator接口部署在數據結構的Symbol.Iterator屬性,也就是說,一個數據結構,只要有Symbol.Iterator屬性,就是可遍歷的。
舉個例子吧~ 數組的Symbol.iterator屬性
let arr = ['a', 'b', 'c'];
let arrIterator = arr[Symbol.iterator]();
arrIterator.next();
複製代碼
上面代碼中,變量arr是一個數組,原生就具備遍歷器接口,部署在arr的Symbol.iterator屬性上面。因此,調用這個屬性,就獲得遍歷器對象。 對於原生部署Symbol.iterator屬性的數據結構,能夠直接使用for...of進行循環遍歷。
對象也想用for...of怎麼辦?
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
}
複製代碼
(1)解構賦值 對數組和 Set 結構進行解構賦值時,會默認調用Symbol.iterator方法。
let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
x='a'; y='b'
let [first, ...rest] = set;
// first='a'; rest=['b','c'];
複製代碼
(2)擴展運算符 擴展運算符(...)也會調用默認的 Iterator 接口。
// 例一
var str = 'hello';
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
複製代碼
(3)yield*後面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口。
let generator = function* () {
yield 1;
yield* [2,3,4];
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 }
複製代碼
遍歷器對象除了具備next方法,還能夠具備return方法和throw方法。若是你本身寫遍歷器對象生成函數,那麼next方法是必須部署的,return方法和throw方法是否部署是可選的。
return方法的使用場合是,若是for...of循環提早退出(一般是由於出錯,或者有break語句),就會調用return方法。若是一個對象在完成遍歷前,須要清理或釋放資源,就能夠部署return方法。
function readLinesSync(file) {
return {
[Symbol.iterator]() {
return {
next() {
return { done: false };
},
return() {
file.close();
return { done: true };
}
};
},
};
}
複製代碼
上面代碼中,函數readLinesSync接受一個文件對象做爲參數,返回一個遍歷器對象,其中除了next方法,還部署了return方法。下面的兩種狀況,都會觸發執行return方法。
說到遍歷,首先就能想到,for,forEach,while,for...in。
那麼,問題來了,for...of有什麼優點呢?
說到底,本節課主要是仍是介紹for...of,介紹Iterator最主要的目的是,爲了Generator函數服務,可是,Generator函數複雜了點兒,接下來咱們還會介紹async...await.
若是你以爲小編寫的不錯,必定要點個贊👍,給個關注呦~