介绍
- 顺序访问一个集合(通常是数组)
- 使用者无需知道集合内部的结构
演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Iterator { constructor(container) { this.list = container.list this.index = 0 } next() { if (this.hasNext()) { return this.list[this.index++] } } hasNext() { if (this.index >= this.list.length) { return false } return true } }
class Container { constructor(list) { this.list = list }
getIterator() { return new Iterator(this) } }
let container = new Container([1, 2, 3, 4, 5, 6]) let iterator = container.getIterator() while (iterator.hasNext()) { console.log(iterator.next()); }
|
场景
jQuery each
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <p>jquery each</p> <p>jquery each</p> <p>jquery each</p> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> let arr = [1, 2, 3, 4, 5, 6] let nodeList = document.getElementsByTagName('p') let $p = $('p')
arr.forEach(item => { console.log(item); });
for (let i = 0; i < nodeList.length; i++) { console.log(nodeList[i]); }
$p.each(function(key, p) { console.log(key, p); })
</script>
|
ES6 Iterator
1 2 3 4 5 6 7 8 9 10
| function each(data) { var $data = $(data) $data.each(function(key, val) { console.log(key, val); }) } each(arr) each(nodeList) each($a)
|
- ES6 中有序的数据类型已经有很多
- Array
- Map
- Set
- String
- TypedArray
- arguments
- nodeList
- 需要有一个统一的遍历接口来遍历这些数据结构
注意 object 不是有序集合,可以用 Map 代替
ES6 Iterator 是什么
- 以上的数据类型,都有
[Symbol.iterator]
属性
[Symbol.iterator]
属性值是函数,执行函数返回一个迭代器
- 这个迭代器就有
next
方法可顺序迭代子元素
- 可运行
Array.prototype.[Symbol.iterator]
来测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| function each(data) { let iterator = data[Symbol.iterator]()
let item = {done: false} while(!item.done) { item = iterator.next() if (!item.done) { console.log(item.value); } } }
function each(data) { for (const item of data) { console.log(item); } }
let arr = [1, 2, 3, 4, 5, 6] let nodeList = document.getElementsByTagName('p') let m = new Map() m.Set('a', 100) m.Set('b', 100)
each(arr) each(nodeList) each(m)
|
ES6 Iterator 与 Generator
- Iterator 的价值不限于上面提到的类型
- 还有 Generator 函数的使用
- 即只要返回的数据符合 Iterator 接口的要求
- 即可使用 Iterator 语法,这就是迭代器模式
设计原则验证
- 迭代器对象和目标对象的分离
- 迭代器将使用者和目标对象隔离
- 符合开放封闭原则