迭代模式:
提供一種方法可以順序獲得聚合對象中的各個元素,是一種最簡單也是最常見的一種設計模式。它可以讓用戶透過特定的接口巡訪集合中的每一個元素而不用瞭解底層的實現
迭代器簡介:
依照與迭代模式的思想而實現,分爲內部迭代器和外部迭代器
內部迭代器:
本身是函數,該函數內部定義好迭代規則,完全接手整個迭代過程,外部只需要一次初始化調用
Array.prototype.forEach
外部迭代器:
本身是函數,執行返回迭代對象,迭代下一個元素必須顯示調用,調用複雜度增加,但靈活性增強
function outerIterator() {} 外部迭代器
迭代器目的
從迭代模式思想中可以看出,就是要標準化 迭代操作
舉個例子
服務端提供數組數據給前端,前端for循環遍歷,但由於業務變化,使得數據結構發生變化,返回對象或者set map,導致前端遍歷代碼大量重寫
解決方案
ES6引入Iterator,部署在NodeList Arguments Array Set Map String等數據的Symbol.iterator屬性上
console.log(Symbol('Symbol.iterator'), Symbol.iterator)
使得這些數據是iterable可迭代的,能進行for…of… Array.from()等操作
Iterator
概念:
遍歷器(Iterator)就是這樣一種機制。它是一種接口,爲各種不同的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數據結構的所有成員),也就是說主要是給for…of…進行消費
iterator實現規則:
next value done
根據規則:手動模擬一個簡單demo
let arr = [1, 3, 5]
function OuterIterator(o) {
let curIndex = 0
let next = () => {
return {
value: o[curIndex],
done: o.length === ++curIndex
}
}
return { next }
}
let oIt = OuterIterator(arr)
Symbol
概念: 一種新的數據結構
出現原因: ES5 的對象屬性名都是字符串,這容易造成屬性名的衝突。比如,你使用了一個他人提供的對象,但又想爲這個對象添加新的方法(mixin 模式),新方法的名字就有可能與現有方法產生衝突。如果有一種機制,保證每個屬性的名字都是獨一無二的就好了,這樣就從根本上防止屬性名的衝突。
let oS = Symbol('abc')
console.log(oS)
// 這個例子說明了Symbol如果傳入的是一個對象,那麼會調用Object.prototype.toString()的方法,下邊是進行了重寫
let oS1 = Symbol({
value: 'chen',
toString: function() {
return 'i love study'
}
})
console.log(oS1)
特點:
唯一,可以作爲對象的屬性,有靜態屬性Symbol.iterator(對應的是一個遍歷器生成函數)
這個demo體現了唯一性
let oS = Symbol('abc')
let oS1 = Symbol('abc')
// 唯一
console.log(oS1 == oS) // false
根據以上的知識,那麼我們可以嘗試在對象上實現for…of遍歷功能
var obj = {
0: 'chen',
1: 'chongxuan',
length: 2,
// 至於屬性名Symbol.iterator,它是一個表達式,返回Symbol對象的iterator屬性,這是一個預定義好的、類型爲 Symbol 的特殊值,所以要放在方括號內
[Symbol.iterator]: function() {
let curIndex = 0
let next = () => {
return {
value: this[curIndex],
done: this.length == curIndex++
}
}
return { next }
}
}
console.log([...obj])
for (let prop of obj) {
console.log(prop)
}