用Symbol.iterator(或yield)实现for...of遍历对象

iterator

迭代器,它是用于访问集合类的标准访问方法,它可以把访问逻辑从不同类型集合中抽象出来,从而避免向外部暴露集合内部的结构。
比如我们访问一个数组可能使用for循环或者map,foreach,filter等for(int i=0; i<array.size(); i++) { ... get(i) ... }, 但是当我们想要遍历链表(linkedlist)的时候就得使用while循环while((e=e.next())!=null) { ... e.data() ... }
以上两种方式我们都必须知道集合的内部结构是怎么样的我们才可以使用对应的循环方式去循环整个集合,那么这样就造成了很大的耦合度,当我们把一个集合的类型从Arrarlist变成Linkedlist的时候,那么原来客户端的代码必须重写,因为我们集合变了,遍历的方式也必须改成对应的方式。
为解决以上问题,Iterator模式总是用同一种逻辑来遍历集合: for(Iterator it = c.iterater(); it.hasNext(); ) { ... },这样就在一定程度上解决了以上的问题。

遍历的方法

遍历数组的方法有很多,这里就不在赘叙了。这里我们就来看一下JS提供给我们用来遍历对象的方法:for…in

Array.prototype.sayHello = function() {
	console.log("Hello")
}
Array.prototype.str = 'world';
var arr = ['a', 'b', 'c'];
arr.name = '数组';

for (const key in arr) {
	console.log(key);
	console.log(typeof key);
	console.log(arr[key]);
}
// 输出的是:
// 0 string a
// 1 string b
// 2 string c
// name string 数组
// sayHello string [Function]
// str string world

那么除了for…in之外,还有什么其他方法呢?答案就是现在我们要说的for…of啦!
首先,我们先来了解下for…of的写法,我们这里用for…of遍历上面的数组,看看是什么结果

for (const value of arr) {
	console.log(value);
}
// 输出:a,b,c

for…of是 ES6 为了弥补for…in的不足而补充的,目前能够实现遍历的对象有arraystringargument以及后面更高级的setMap

详细的看我上一篇 for,for in , for of 和forEach四者对比

是的,for…of暂时还没有实现对object的遍历,但是我们可以通过Symbol.iterator给对象添加这个塑性,我们就可以使用for-of了,代码如下:

var person={
	name:'henry',
	age:26,
	sex:'male'
}
Object.defineProperty(person,Symbol.iterator,{
	enumberable:false,
	configurable:false,
	writable:false,
	value:function(){
		var _this=this;
		var nowIndex=-1;
		var key=Object.keys(_this);
		return {
			next:function(){
				nowIndex++;
				return {
					value:_this[key[nowIndex]],
					done:(nowIndex+1>key.length)
				}
			}
		}
	}
})
}
//这样的话就可以直接通过for...of来遍历对象了

for(var value of person){
  console.log(value )
}
//输出的是:henry,26,male

其实for-of的原理最终也是通过调用person[Symbol.iterator]()这个函数,这个迭代器函数返回一个next函数,for循环会不断调用next。那么知道原理之后,我们可以自己来模拟一下for…of的内部逻辑

//数组对象
var array = {}
array[Symbol.iterator] = function() {
  let index = 1;
  return {
    next() {
      return {done: index>100, value: index++}
    }
  }
}
//for...of内部,外部传进一个value和一个array
var iterator = array[Symbol.iterator]();
var generator=iterator.next();
while(!generator.done) {
  value = generator.value;
  console.log(generator.value);
  generator=iterator.next();
}

上面使用 iterator.next 和 while 结合实现了 for…of循环。 除了使用iterator 之外,我们还可以使用 yield 语法来实现循环,yield相对简单一些,只要通过 yield 语句把值返回即可:

let array = {
  [Symbol.iterator]: function*() {
    for(var i=0;i<=100;i++) {
      yield i;
    }
  }
}
for(var value of array ) {
  console.log(value);
}
//这个yield其实最后返回的就是iterator函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值