JavaScript — 设计模式 行为型设计模式-迭代器模式

释放双眼,带上耳机,听听看~!

迭代器模式:提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示。迭代器模式的特点在于顺序访问一个集合,使用者无需知道内部结构。

在现实生活中好像例子不多,但是熟悉ES6的工程师应该知道es6中有iterator。我们先不看这个,先写一个小的demo代码来熟悉迭代器。

我们先看一下迭代器的UML类图

JavaScript -- 设计模式 行为型设计模式-迭代器模式

 


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
1class Iterator {
2    constructor(container) {
3        this.list = container.list;
4        this.index = 0;
5    }
6    next() {
7        if (this.hasNext()) {
8            return this.list[this.index++];
9        } else this.index++;
10        return null;
11    }
12    hasNext() {
13        return this.index < this.list.length;
14    }
15}
16class Container {
17    constructor(list) {
18        this.list = list;
19    }
20    getIterator() {
21        return new Iterator(this);
22    }
23}
24
25const arr = [1, 2, 3, 4, 6];
26
27const iter = new Container(arr).getIterator();
28while (iter.hasNext()) {
29    console.log(iter.next());
30}
31

JavaScript -- 设计模式 行为型设计模式-迭代器模式

我们获取到迭代器对象后,无需关注迭代器是如何遍历子元素的,只需要简单的调用next函数即可。

 

ES6的iteractor你可能没有用过,但是for of循环你肯定使用过。

在JS当中,有很多有顺序的聚合对象比如array,map, set, nodeList, arguments,类数组,这些数据类型上面有一个Symbol.iterator属性,该值是一个函数用于返回一个迭代器,该迭代器上面有一个next函数。


1
2
3
4
1const arr = [1, 2, 3, 4, 6];
2const ite = arr[Symbol.iterator]();
3console.log(ite);
4

JavaScript -- 设计模式 行为型设计模式-迭代器模式

我们来使用ES6的iterator来遍历该数组。


1
2
3
4
5
6
7
8
9
10
11
12
1const arr = [1, 2, 3, 4, 6];
2let iterator = arr[Symbol.iterator]();
3
4let item = iterator.next();
5while (!item.done) {
6    console.log(item);
7    item = iterator.next();
8}
9
10console.log(iterator.next());
11console.log(iterator.next());
12

JavaScript -- 设计模式 行为型设计模式-迭代器模式

value:表示当前遍历的值  done表示是否结束 true表示结束

我们来封装一个each方法,来实现遍历。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1const arr = [1, 2, 3, 4, 6];
2const set = new Set();
3set.add(1);
4set.add(2);
5set.add(3);
6set.add(4);
7
8
9function each(data) {
10    let iterator = data[Symbol.iterator]();
11    let item = iterator.next();
12    while (!item.done) {
13        console.log(item.value);
14        item = iterator.next();
15    }
16}
17
18console.log("数组遍历");
19each(arr);
20console.log("set遍历");
21each(set);
22

这样其实很麻烦,幸好ES6封装了for of循环 这个我们就不掩饰了,非常简单。

 

Generator函数


1
2
3
4
5
6
7
8
1function* list() {
2    yield 1;
3    yield 2;
4    yield 3;
5}
6const l = list();
7each(l);
8

JavaScript -- 设计模式 行为型设计模式-迭代器模式

Generator函数返回的是可以迭代的对象,我们可以使用each(上面封装的方法)或 for of来遍历。

 

我们知道Object没有迭代器,不能使用for of循环,那么我们可以通过Generator来实现for of遍历Obejct


1
2
3
4
5
6
7
8
9
10
1function *getObjectIterator(obj) {
2    for(let key in obj) {
3        yield obj[key];
4    }
5}
6const obj = { name: "cyl", age: 16 }
7for (let v of getObjectIterator(obj)) {
8    console.log(v);
9}
10

JavaScript -- 设计模式 行为型设计模式-迭代器模式

 

我们可以利用Generator和for of来实现一些复杂的遍历,而且不必向调用者暴露细节。

 

 

给TA打赏
共{{data.count}}人
人已打赏
安全技术

md5 加密算法

2021-8-18 16:36:11

安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索