Iterator 和 for...of
阿新 • • 發佈:2021-01-20
Iterator 的作用有三個:
- 是為各種資料結構,提供一個統一的、簡便的訪問接
- 是使得資料結構的成員能夠按某種次序排列
- 是 ES6 創造了一種新的遍歷命令for...of迴圈,Iterator 介面主要供for...of消費
部署方式
原生就具有iterator的資料結構
- Array
- Map
- Set
- String
- TypedArray
- 函式的 arguments 物件
- NodeList 物件
ES6 規定,預設
的 Iterator 介面部署在資料結構的Symbol.iterator
屬性,或者說,一個數據結構只要具有Symbol.iterator屬性,就可以認為是“可遍歷的”(iterable)。Symbol.iterator屬性本身是一個函式
遍歷器
。至於屬性名Symbol.iterator,它是一個表示式
,返回Symbol物件的iterator屬性,這是一個預定義好的、型別為 Symbol 的特殊值,所以要放在方括號內
// 為一個物件直接部署 const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; } }; } };
一個數據結構執行的for..of.. 迴圈,就會執行該資料結構的[Symbol.iterator]()
obj[Symbol.iterator]()
執行之後返回一個遍歷器物件,其中next()
方法用來移動指標,定義每一次遍歷的操作
throw()方法
return()方法的使用場合是,如果for...of迴圈提前退出(通常是因為出錯,或者有break語句),就會呼叫return()方法。如果一個物件在完成遍歷前,需要清理或釋放資源,就可以部署return()方法。
function readLinesSync(file) { return { [Symbol.iterator]() { return { next() { return { done: false }; }, return() { file.close(); return { done: true }; } }; }, }; } //以下都會呼叫return方法 // 情況一 for (let line of readLinesSync(fileName)) { console.log(line); break; } // 情況二 for (let line of readLinesSync(fileName)) { console.log(line); throw new Error(); }
物件部署iterator的方式
使用類
class RangeIterator {
constructor(start, stop) {
this.value = start;
this.stop = stop;
}
[Symbol.iterator]() { return this; } // 使用for of 迴圈是預設呼叫此方法 返回當前的例項化物件,該物件有一個next方法
next() { // 返回值定義了該iterator的操作
var value = this.value;
if (value < this.stop) {
this.value++;
return {done: false, value: value};// done: false 可以省略
}
return {done: true, value: undefined };// value: undefined 可以省略
}
}
function range(start, stop) {
return new RangeIterator(start, stop);
}
for (var value of range(0, 3)) {
console.log(value); // 0, 1, 2
}
建構函式的原型鏈上部署
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; // 修改指標指向 保證Iterator的功能
two.next = three;
for (var i of one){
console.log(i); // 1, 2, 3
}
類陣列部署
類似陣列的物件(存在數值鍵名和length屬性),部署 Iterator 介面,有一個簡便方法,就是Symbol.iterator方法直接引用陣列的 Iterator 介面。
或者直接轉換成為類陣列
- 普通物件部署陣列的Symbol.iterator方法,並無效果
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
[...document.querySelectorAll('div')] // 可以執行了