【JS】從ECMA深入學習Iterator的執行機制和原理
阿新 • • 發佈:2021-01-22
技術標籤:Javascript前端javascriptes6
前置:前後加了 % 代表著這是 ECMAScript 內部抽象化的語言表現形式。例如:我們看到的 Object.prototype 在語言內部抽象後所表現的就是 %ObjectPrototype%。其實所代表的就是 Object 的 原型方法。JS
Iterator遍歷器
ES中,Array、Object、Map、Set是表示“集合”的資料結構。從抽象一些的角度來看,它們都是由多個元素/資料組合而成的。Iterator就是一種介面,為不同的資料結構提供同意的訪問機制。ES6中,如果要使用for...of...
和 yield*
iterator介面內容
- next()方法(必選):返回值為IteratorResult物件
- return()方法(可選):返回一個done為true的IteratorResult,呼叫這個方法表示後續不能再進行next方法了
- throw()方法(可選):呼叫此方法表示遍歷過程當中出現錯誤。
IteratorResult介面
屬性 | 型別 | 描述 |
---|---|---|
done | true/false | done不存在預設為false,如果遍歷到結束位置,為true |
value | 任意型別 | value值不一定會返回,done為false返回遍歷到的當前元素,done為true返回this物件。 |
ES6文件中,提到所有實現了Iterator介面的物件,都繼承了%IteratorPrototype% Object。我們就來看看這個物件包括什麼。
遍歷器原型物件(%IteratorPrototype% Object)
ES6規範中,提供了可以直接獲取到%IteratorPrototype% Object的程式碼:
Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))
ecma262/#sec-%iteratorprototype%-object
我們可以看到,這個物件當中有個名為[Symbol.iterator]
的方法。該方法最後返回this。
既然每個實現Iterable都繼承了這個原型物件,那麼說明,實現Iterable物件的話也需要實現[Symbol.iterator]()
- 用ts程式碼表示Iterable介面可以表現如下
interface Iterable{
[Symbol.iterator]():Iterator
}
interface Iterator{
next(value?:any):IteratorResult
}
interface Iterator{
value:any,
done:boolean
}
es6.ruanyifeng.com/#docs/iterator
因此,我們可以看到如果一個數據結構具有Symbol.iterator屬性,就可以認為是可遍歷的。可以使用for…of去迴圈。
iterator遍歷過程
- 建立一個指標物件,指向當前資料結構的起始位置。
- 呼叫指標物件的next昂法,把指標指向資料結構的第一個成員。
- 繼續呼叫next,指標指向下一個成員。直到當前的位置已經超出了陣列的長度,說明已經到達結束位置了。
//實現一個iterator
//定義一個方法,傳入一個物件,返回一個可列舉的物件,
//呼叫next方法會輸出傳入obj裡面的key-value值
//(暫時認為物件取值只包含數字和字串)
Input: var obj = {
'pos1':1,
'pos2':2
'pos3':3
}
Output:
{value:{'pos1':1},done,false},
{value:{'pos2':2},done,false},
{value:{'pos3':3},done,false},
什麼時候呼叫Iterator介面
- 解構賦值
- 擴充套件運算子
- yield*
- for…of、Array.from、Map(),Set(),WeakMap(),WeakSet(),promise.all,promise.race