本文以 用 for of
遍历 Object
为引 来聊聊 迭代器模式。
什么是迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。 ——《设计模式:可复用面向对象软件的基础》
可以说迭代器模式就是为了遍历存在的。提到遍历,大家都对那些手段耳熟能详了,下面我们先简单列一下各种数据类型的遍历:
遍历数组
for
循环forEach
map
reduce
keys
values
for of
- ......
其中keys
values
for of
需要Iterator
支持,后面会介绍Iterator
遍历 Map/Set
keys
entries
forEach
- ......
遍历 Object
for in
- 先
Object.keys(obj)
得到对象每个属性的数组, 然后使用数组的遍历方法遍历每个key
,就能获取 每个key
对应的value
Iterator
和 for of
Iterator
是ES6提出的一个接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator
接口,就可以完成遍历操作。
Iterator
的作用
- 为各种数据结构,提供一个统一的、简便的访问接口。
- ES6提出了新的遍历命令
for...of
循环,Iterator
接口主要供for...of
消费。
Iterator
的遍历过程
既然数组是支持for...of
循环的,那数组肯定部署了 Iterator
接口,我们通过它来看看Iterator
的遍历过程。
从图中我们能看出:
Iterator
接口返回了一个有next
方法的对象。- 每调用一次 next,依次返回了数组中的项,直到它指向数据结构的结束位置。
- 返回的结果是一个对象,对象中包含了当前值
value
和 当前是否结束done
用 for of 遍历 Object
回到标题中的问题,我们现在如何去让一个对象也可以用 for of
来遍历它呢?
根据上面讲到的内容,需要给对象也部署 Iterator
接口(其实就是在Object.prototype
上实现一个以Symbol.iterator
为名的function
,这个function
返回一个有next
方法的对象,每调用一次 next
, 能够依次返回数组中的项,直到它指向数据结构的结束位置 )
function objectIterator() { const keys = Object.keys(this) let index = 0 return { next: () => { const done = index >= keys.length const value = done ? undefined : this[keys[index]] index++ return { done, value } } } } Object.prototype[Symbol.iterator] = objectIterator const obj = { key: '1', value: '2' } for (const iterator of obj) { console.log(iterator) }