迭代器模式

迭代器模式

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

迭代器的特点
  1. 访问一个聚合对象的内容而不需要暴露它的内部表示
  2. 为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作

许多浏览器也支持JavaScript的Array.prototype.forEach。

forEach的使用示例如下:

	var arr = [1,2,3,4,5,6,7];
	var arr1 = ['a','b','c','d','e','f'];
	arr.forEach(function(value,index,array){
		console.log("第"+index+"个元素的值为"+value+"原数组:"+array);
	})
	arr.forEach(function(value,index,array){
		console.log("第"+index+"个元素的值为"+value+"原数组:"+array);
		console.log(this);//这个里面的this指向arr1
		console.log(this[index]);//访问arr1中下表为index的值
	},arr1)
jQuery的迭代器

迭代器无非就是循环访问聚合对象中的各个元素。入jQuery中的$.each函数,其中毁掉函数中的参数i为当前的索引,n为当前元素。

示例:

  1. 迭代数组
	var arr = [1,22,3,4,5,6]
	$.each(arr,function(i,value){
		console.log('下标:'+i+"值:"+value);
	});
  1. 迭代DOM树
<div id="box">
	<ul>
		<li>li-1</li>
		<li>li-2</li>
		<li>li-3</li>
		<li>li-4</li>
		<li>li-5</li>
	</ul>
</div>
$(function(){
	var liElem = $("#box li");
	$.each(liElem,function(i,item){
		console.log(i+":"+$(this).text());
		console.log(this)
		//给每个li添加一个点击事件
		$(this).click(function(){
			alert(i+":"+$(this).text())
		})
	})
	
	//或如下代码
	$("#box li").each(function(i,item){
		console.log(i+":"+$(this).text());
		console.log(this)
	})
})
实现自定义的迭代器

模拟一个each函数,each函数接受2个参数,第一个参数为被循环的数组,第二个参数为循环中的每一步后将被触发的回调函数。如下:

	var arr1 = ['a','b','c','d']
	var each = function(arr,callback){
		for(var i = 0; i < arr.length; i++){
			callback.call(arr[i],i,arr[i]);
            //callback.call(arr1,i,arr[i]);
		}
	}
	
	each([1,2,3,44],function(index,value){
		console.log("第"+index+"个:"+value);
		console.log(this);
	})
内部迭代器和外部迭代器

迭代器可分为内部迭代器和外部迭代器。

1. 内部迭代器

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

内部迭代器在调用的时候非常方便,不需要关心迭代器内部的实现,跟迭代器的交互也仅仅是一次初始调用,但者也是迭代器的缺点。这是由于内部迭代器的迭代规则已经被提前规定。

示例:判断两个数组里的元素的值是否完全相同;不该写each函数本身的代码,则只能修改each函数的回调函数

	var each = function(arr,callback){
		for(var i = 0; i < arr.length; i++){
			callback.call(arr[i],i,arr[i]);
		}
	}
	var compare = function(arr1,arr2){
		if(arr1.length !== arr2.length){
			throw new Error('两个数组不相等,长度不同');
		}
		each(arr1,function(index,value){
			if(value !== arr2[index]){
				throw new Error("两个数组不相等,详见下标为"+index);
			}
		});
		alert('两个数组相等');
	}
	
	compare([1,2,3,4],[1,2,3])
	compare([1,2,3],[1,2,3,4])
	compare([1,2,3],[1,2,3])
	compare([1,2,3],[1,2,'3'])

总结

compare这个函数一点点也不好,能完成要求还是因为Javascript可以把函数当作参数传递的特性。

在一些没有闭包的语言中,内部迭代器本身的实现也是相当复杂的。比如:C语言中的内部迭代器使用函数指针来实现的,循环处理所需要的数据都是要以参数的形式明确地从外面传递进去。

2.外部迭代器

外部迭代器必须显示的请求迭代下一个元素

外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性。

	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 aindex = function(){
			return current
		}
		return {
			next: next,
			isDone:isDone,
			getCurrItem:getCurrItem,
			aindex:aindex
		}
	}
	var compare = function(iterator1,iterator2){
		//如果有一个没有遍历完那么应该进行继续执行
		while(!iterator1.isDone() || !iterator2.isDone()){
			//判断长度是否相等
			if(iterator1.isDone() && iterator2.isDone()){
				throw new Error('not eq of len,index is:'+iterator1.aindex());
			}
			if(iterator1.getCurrItem() !== iterator2.getCurrItem()){
				throw new Error('not eq,index is:'+iterator1.aindex());
			}
			iterator1.next();
			iterator2.next();
		}
		alert('eq');
	}
	var iterator1 = Iterator([1,2,'3',4]);
	var iterator2 = Iterator([1,2,3]);
	console.log(iterator1)
	compare(iterator1,iterator2)

总结

外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。内部迭代器和外部迭代器在实际生产中没有优劣之分,

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

迭代器模式不仅可以迭代数组,还可以迭代一些类数组对象。如:arguments、{“0”:1,“1”:2},无论是类内部迭代器还是外部迭代器,只要被迭代的对象具有length属性而且可以使用下标访问,那么就可以进行迭代。

在Javascript中,for in语句可以用来迭代普通字面量对象属性。jQuery函数通过$.each函数来封装各种迭代行为。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值