js设计模式-迭代器模式

迭代器模式介绍

定义:迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
使用的好处:迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

先看一个 仿jquery 迭代器

1
2
3
4
5
6
7
8
9
10
11
var $ = {
each: function (arr, fn) {
for (var i = 0, len = arr.length; i < len; i++) {
fn.call(arr[i], i, arr[i])
}
}
};

$.each([1, 2, 3, 4, 5, 6], function(i, val) {
console.log([i, val]);
});

迭代器的分类

迭代器根据实现的位置,我们将它分为内部迭代器和外部迭代器两种。

内部迭代器

内部迭代器对于使用者来说他不用关心迭代器的内部实现,只用关注使用的效果,我们上面仿jQuery的each就是个内部迭代器的实现。

内部迭代器有它的好处但是也有它的不足,比如我们要比较两个数组是否相等,上面的方法就不满足我们的需要,我们就需要写一个新的方法来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var $ = {
each: function (arr, fn) {
for (var i = 0, len = arr.length; i < len; i++) {
fn.call(arr[i], i, arr[i])
}
}
};

var compareArray = function(arr, arr2) {
if( arr.length !== arr2.length) {
return false;
}

$.each(arr, function(i, val) {
if( val !== arr2[i]) {
return false;
}
});
return true;
};

compareArray([1, 2], [1, 2, 3]); // false

外部迭代器

外部迭代器必须显式地请求才会迭代下一个元素。

外部迭代器虽然增加了使用上的一些麻烦,但是它的灵活性却正是我们需要的。我们可以人为的控制迭代的过程和顺序。

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
37
38
39
40
41
42
43
44
45
46
47
// 迭代器实现
var Iterator = function(obj) {
var current = 0;

var next = function() {
current += 1;
};

var isDone = function() {
return current >= obj.length;
};

var getCurrItem = function() {
return obj[current];
};

var len = function() {
return obj.length;
}

return {
next: next,
isDone: isDone,
getCurrItem: getCurrItem,
length: len,
}
};
// 比较数组
var compareArray = function (iteratorObj, iteratorObj2) {
if(iteratorObj.length !== iteratorObj2.length) {
return false;
}
while (!iteratorObj.isDone() && !iteratorObj2.isDone()){
if (iteratorObj.getCurrItem() !== iteratorObj2.getCurrItem()){
return false;
}
iteratorObj.next();
iteratorObj2.next();
}

return true;
};

var arr = Iterator([1, 2, 3]);
var arr2 = Iterator([1, 2, 3]);

compareArray(arr, arr2); // true

迭代器可以中止

在for循环中,我们可以通过break来跳出循环,所以在迭代器模式中。我们可以利用这个来提前终止迭代。接下来我们改在一下最开始的each函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var each = function(arr, callback) {
var result
for (var i = 0, len = arr.length; i < len; i++) {
result = callback.call(arr[i], i, arr[i])
if (result === false) {
break
}
}
}

each([1,2,3,4,5,6,7], function(i, el) {
if (el > 3) {
return false
}
console.log(el)
})
Buy me a cup of coffee,thanks!