Interator "集合"數據的結構主要有 、 、 and ,任何數據結構只要部署 Iterator 介面,就可完成遍歷操作 遍歷過程: 創建指針,指向當前數據結構起始位。(遍歷對象本質是一個指針對象)。 依次迴圈調用指針對象的 方法,對應指向數據結構成員,直至結束。 ` 每次調用 方法,返回對象 ...
Interator
"集合"數據的結構主要有
Array
、Object
、Set
andMap
,任何數據結構只要部署 Iterator 介面,就可完成遍歷操作
遍歷過程:
- 創建指針,指向當前數據結構起始位。(遍歷對象本質是一個指針對象)。
- 依次迴圈調用指針對象的
next
方法,對應指向數據結構成員,直至結束。
每次調用
next方法,返回對象當前成員的信息
{value:text,done:true},其中
value表示成員值,
done` 表示遍歷是否結束
let arr = ['Owen','18'];
let makeInterator = array =>{
let index = 0;
return {
next (){
return index < array.length ?
{value:array[index++],done:false} :
{value:undefined, done:true}
}
}
}
let inter = makeInterator(arr);
inter.next()
it.next() // { value: "Owen", done: false }
it.next() // { value: 18, done: false }
it.next() // { value: undefined, done: true }
對與遍歷器對象來說 done: false
and value:undefined
可省略
原生具備 Iterator 的數據結構:Array
、 String
、 Map
、 Set
、arguments
and NodeList
都預設部署
[Symbol.iterator]
方法
//
const obj = {
[Symbol.iterator] : function () {
return {
next: function () {
return {
value: 1,
done: true
};
}
};
}
};
obj[Symbol.iterator]().next() //{value: 1, done: true}
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 }
iter.next() // { value: undefined, done: true }
對象(Object)之所以沒有預設部署 Iterator 介面,是因為對象的哪個屬性先遍歷,哪個屬性後遍歷是不確定的,需要開發者手動指定。
//原型上部署Interator
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
}
//對象上部署Interator
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;
current = current.next;
return { done: false, 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
}
類似數組對象,可引用 Array.prototype[Symbol.iterator]
//NodeList
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
[...document.querySelectorAll('div')]
//obj
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'
}
一些 預設調用 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'];
//擴展運算符
var str = 'hello';
[...str] // ['h','e','l','l','o']
let arr = ['b', 'c'];
['a', ...arr, 'd'] // ['a', 'b', 'c', 'd']
//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 }
// for...of
//for...of迴圈可以使用的範圍包括數組、Set 和 Map 結構、某些類似數組的對象(比如arguments對象、DOM NodeList 對象)、 Generator 對象,以及字元串。
let arr = document.querySelectorAll("p");
for (let item of arr ) {
console.log(item)
}
/* 其他操作*/
Array.from()
Map(), Set(), WeakMap(), WeakSet() //生成對應數據結構
Promise.all()
Promise.race()
遍歷器return方法和throw方法
return()
return方法必須返回一個對象。
如果一個對象在完成遍歷前,需要清理或釋放資源,就可以部署return方法。
如果for...of迴圈提前退出(通常是因為出錯,或者有break語句),就會調用return方法。
function readFile(file) {
return {
[Symbol.iterator]() {
return {
next() {
return {done:false}
},
return(){
file.close()
return {done:true}
}
};
}
};
}
//觸發 return()
for (let line of readFile(fileName)) {
console.log(line);
break;
}
//觸發 return()
for (let line of readLinesSync(fileName)) {
console.log(line);
throw new Error();
}
for...of 和其他遍歷語法對比
let arr = [1,2];
//普通 `for`迴圈
for (var index = 0; index <arr.length; index++) {
console.log(arr[index]);
}
/**
* 書寫比較麻煩
*/
// Array.forEach
arr.forEach(function(item){
console.log(item)
})
/**
* 無法跳出迴圈,無法使用 break or return
*/
// for...in
for (let index in arr) {
console.log(arr[index]);
}
/**
* 1.數組鍵名為字元串形式的數字
* 2.會遍歷出原型鏈上的鍵,和手動添加的鍵
* 3.有些情況是無順序遍歷
*/
for (let item of arr) {
console.log(item);
}
/**
* 1.語法簡潔
* 2.沒有 for...in 的缺點
* 3.可以使用 return、break and continue
*
*/