【第七章】 迭代器模式

迭代器模式

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

自己实现一个迭代器:

1
2
3
4
5
6
7
8
var each = function(ary,callback){
for(var i=0;i<ary.length;i++){
callback.call(null,i,ary[i]) // 把下标和元素当作参数传给callback函数
}
}
each([1,2,3],function(i,n){
console.log([i,n])
})

内部迭代器

上面编写的 each 函数属于内部迭代器,each 函数的内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用。

内部迭代器在调用的时候非常方便,外界不用关心迭代器内部的实现,跟迭代器的交互也仅仅是一次初始调用,但这也刚好是内部迭代器的缺点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 内部迭代器实现 比较两个数组
function compare(ary1,ary2){
if(ary1.length != ary2.length){
console.log('不相等')
return
}
each(ary1,function(i,n){
if(ary2[i]!=n){
throw new Error('不相等') // console.log('不相等')
}
})
console.log('相等')
}
compare([1,2,3],[1,2,3]) // 相等

外部迭代器

外部迭代器必须显式地请求迭代下一个元素。
外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,我们可以手工控制迭代的过程或者顺序。

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
var Iterator = function(obj){
var current = 0
var next = function(){
current +=1
}
var isDone = function(){
return current >= obj.length
}
var getCurrentItem = function(){
return obj[current]
}
return {
next: next,
isDone: isDone,
getCurrentItem: getCurrentItem
}
}

// 外部迭代器实现 比较两个数组
function compare(Iterator1,Iterator2){
while(!Iterator1.isDone()&&!Iterator2.isDone()){
if(Iterator1.getCurrentItem() !== Iterator2.getCurrentItem()){
throw new Error('不相等')
}
Iterator1.next()
Iterator2.next()
}
console.log('相等')
}
var Iterator1 = Iterator([4,5,6])
var Iterator2 = Iterator([4,5,6])
compare(Iterator1,Iterator2) // 相等

迭代类数组对象和字面量对象

类数组:arguments
字面量对象:{‘0’:’a’,’1’:’b’}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function each(obj,callback){
var value,
i=0,
length = obj.length,
isArray = isArraylike(obj); //假装封装好了一个判断是否是类数组的方法

if(isArray){ // 迭代类数组
for(;i<length;i++){
value = callback.call(null,i,obj[i])
if(value === false){
break;
}
}
}else{
for(i in obj){
value = callback.call(null,i,obj[i])
if(value === false){
break;
}
}
}
return obj
}

中止迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
var each = function(ary,callback){
for(var i=0;i<ary.length;i++){
if(callback(i,ary[i]) === false){
break
}
}
}
each([11,21,31,41,51],function(){
if(n>30){
return false
}
console.log(n)
}) // 11 21

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2019-2023 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信