你知道JavaScript中的可迭代物件與迭代器嗎
Lazy evaluation
Lazy evaluation常被譯為“延遲計算”或“惰性計算”,指的是僅僅在真正需要執行的時候才計算表示式的值。
與惰性求值相反的是及早求值(eager evaluation)及早求值,也被稱為貪婪求值(greedy evaluation)或嚴格求值,是多數傳統程式語言的求值策略。
充分利用惰性求值的特性帶來的好處主要體現在以下兩個方面:
避免不必要的計算,帶來效能上的提升。
節省空間,使得無限迴圈的資料結構成為可能。
迭代器
ES6 中的迭代器使惰性求值和建立使用者定義的資料序列成為可能。迭代是一種遍歷資料的機制。 迭代器是用於遍歷資料結構元素(稱為Iterable)的指標,用於產生值序列的指標。
迭代器是一個可以被迭代的物件。它抽象了資料容器,使其行為類似於可迭代物件。
迭代器在例項化時不計算每個專案的值,僅在請求時才生成下一個值。 這非常有用,特別是對於大型資料集或無限個元素的序列。
可迭代物件
可迭代物件是希望其元素可被公眾訪問的資料結構。JS 中的很多物件都是可迭代的,它們可能不是很好的察覺,但是如果仔細檢查,就會發現迭代的特徵:
new Map([iterable])
new WeakMap([iterable])
new Set([iterable])
new WeakSet([iterable])
Promise.all([iterable])
Promise.race([iterable])
Array.from([iterable])
還有需要一個可迭代的物件,否則,它將丟擲一個型別錯誤,例如:
for ... of
... (展開運算子)
const [a, b, ..] = iterable (解構賦值)yield* (生成器)
JavaScript中已有許多內建的可迭代項:
String,Array,TypedArray,Map,Set。
迭代協議
迭代器和可迭物件遵循迭代協議。
協議是一組介面,並規定了如何使用它們。
迭代器遵循迭代器協議,可迭代遵循可迭代協議。
可迭代的協議
要使物件變得可迭代,它必須實現一個透過Symbol.iterator的迭代器方法,這個方法是迭代器的工廠。
使用 TypeScript,可迭代協議如下所示:
interface Iterable { [Symbol.iterator]() : Iterator; }
Symbol.iterator]()是無引數函式。 在可迭代物件上呼叫它,這意味著我們可以透過this來訪問可迭代物件,它可以是常規函式或生成器函式。
迭代器協議
迭代器協議定義了產生值序列的標準方法。
為了使物件成為迭代器,它必須實現next()方法。 迭代器可以實現return()方法,我們將在本文後面討論這個問題。
使用 TypeScript,迭代器協議如下所示:
interface Iterator { next() : IteratorResult; return?(value?: any): IteratorResult; }
IteratorResult 的定義如下:
interface IteratorResult { value?: any; done: boolean; }
done通知消費者迭代器是否已經被使用,false表示仍有值需要生成,true表示迭代器已經結束。
value 可以是任何 JS 值,它是向消費者展示的值。
當done為true時,可以省略value。
組合
迭代器和可以可迭代物件可以用下面這張圖來表示:
事例
基礎知識介紹完了,接著,我們來配合一些事例來加深我們的映像。
範圍迭代器
我們先從一個非常基本的迭代器開始,createRangeIterator迭代器。
我們手動呼叫it.next()以獲得下一個IteratorResult。 最後一次呼叫返回{done:true},這意味著迭代器現在已被使用,不再產生任何值。
function createRangeIterator(from, to) { let i = from; return { next() { if (i <= to) { return { value: i++, done: false }; } else { return { done: true }; } } } } const it = createRangeIterator(1, 3); console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next());
可迭代範圍迭代器
在本文的前面,我已經提到 JS 中的某些語句需要一個可迭代的物件。 因此,我們前面的示例在與for ... of迴圈一起使用時將不起作用。
但是建立符合迭代器和可迭代協議的物件非常容易。
function createRangeIterator (from, to) { let i = from return { [Symbol.iterator] () { return this }, next() { if (i <= to) { return { value: i++, done: false } } else { return { done: true } } } } } const it = createRangeIterator(1, 3) for (const i of it) { console.log(i) }
無限序列迭代器
迭代器可以表示無限制大小的序列,因為它們僅在需要時才計算值。
注意不要在無限迭代器上使用擴充套件運算子(...),JS 將嘗試消費迭代器,由於迭代器是無限的,因此它將永遠不會結束。 所以你的應用程式將崩潰,因為記憶體已被耗盡
同樣,for ... of 迴圈也是一樣的情況,所以要確保能退出迴圈:
function createEvenNumbersIterator () { let value = 0 return { [Symbol.iterator] () { return this }, next () { value += 2 return { value, done: false} } } } const it = createEvenNumbersIterator() const [a, b, c] = it console.log({a, b, c}) const [x, y, z] = it console.log({ x, y, z }) for (const even of it) { console.log(even) if (even > 20) { break } }
關閉迭代器
前面我們提到過,迭代器可以有選擇地使用return()方法。 當迭代器直到最後都沒有迭代時使用此方法,並讓迭代器進行清理。
for ... of迴圈可以透過以下方式更早地終止迭代:
break
continue
throw
return
function createCloseableIterator () { let idx = 0 const data = ['a', 'b', 'c', 'd', 'e'] function cleanup() { console.log('Performing cleanup') } return { [Symbol.iterator]() { return this }, next () { if (idx <= data.length - 1) { return { value: data[idx++], done: false } } else { cleanup() return { done: true } } }, return () { cleanup() return { done: true } } } } const it = createCloseableIterator() for (const value of it) { console.log(value) if (value === 'c') { break } } console.log('n----------n') const _it = createCloseableIterator(); for (const value of _it) { console.log(value); }
如果知道迭代器已經結束,則手動呼叫cleanup()函式。
如果突然完成,則return()起作用併為我們進行清理。
【推薦學習:】
以上就是你知道JavaScript中的可迭代物件與迭代器嗎的詳細內容,更多請關注php中文網其它相關文章!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4369/viewspace-2827534/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python可迭代的物件與迭代器Python物件
- 可迭代物件、迭代器、生成器物件
- Iterator與Iterable(迭代器與可迭代)
- 迭代器與可迭代物件的區別,以及iter()函式的使用。物件函式
- 跟你深入剖析可迭代物件和迭代器的區別與聯絡物件
- Python之可迭代物件、迭代器、生成器Python物件
- 關於python中可迭代物件和迭代器的一些理解Python物件
- 搞清楚 Python 的迭代器、可迭代物件、生成器Python物件
- Python中可迭代物件、迭代器以及iter()函式的兩個用法詳解Python物件函式
- 你可能不知道的迭代器與生成器
- 關於我對可迭代物件,迭代器,生成器的一些理解物件
- javascript 之迭代器JavaScript
- JavaScript的迭代函式與迭代函式的實現JavaScript函式
- 你知道 JavaScript 中的 Arguments 物件都有哪些用途嗎?JavaScript物件
- Python進階:迭代器與迭代器切片Python
- 《python-美藏篇》1.可迭代、迭代器與生成器Python
- 不用for迭代 --手工訪問迭代器中的元素.
- python中的迭代器Python
- 【python】迭代器與生成器到底是什麼?看完你就知道Python
- 協程與迭代器
- JavaScript 遍歷、列舉與迭代JavaScript
- 迭代與遞迴--你被遞迴搞暈過嗎?遞迴
- STL中的迭代器分類
- Python中迭代器的實現Python
- 迭代器
- JavaScript 之迭代方法JavaScript
- JavaScript 設計模式(六) 迭代器模式JavaScript設計模式
- Javascript設計模式之迭代器模式JavaScript設計模式
- 迭代器與生成器
- [OI] 指標與迭代器指標
- ES6系列--7. 可迭代協議和迭代器協議協議
- 迭代器的 ConcurrentModificationExceptionException
- 從迭代器模式到迭代協議模式協議
- javascript設計模式 之 4 迭代器模式JavaScript設計模式
- 前端面試複習2:迭代器,生成器與非同步迭代器前端面試非同步
- Python迭代器與生成器Python
- TypeScript迭代器TypeScript
- Python 迭代器Python