解读JavaScript迭代器

1.理解迭代

2.理解可迭代对象

3.理解迭代器

前言
说到迭代器,在学习C++时一般只是使用auto iterator来遍历一个容器,当时也就只把他当做一个通用指针。深入一点可能探讨了一下迭代器失效原理之类的,但对这个东西其实一直是一种抽象的感官,今天就借着红宝书来细细品读一下这个东西。

1.理解迭代:

首先看一段红宝书原话:

迭代的英文“iteration”源自拉丁文itero,意思是“重复”或“再来”。在软件开发领域,“迭代”的意思是按照顺序反复多次执行一段程序,通常会有明确的终止条件。
循环是迭代机制的基础,这是因为它可以指定迭代的次数,以及每次迭代要执行什么操作。每次循环都会在下一次迭代开始之前完成,而每次迭代的顺序都是实现定义好的。

上述内容可能很抽象,但如果把迭代换成一个词理解就很简单了。“遍历”这个词大家很熟悉,毕竟一接触编程我们做过遍历数组。那如果我们把“迭代”直接换成“多次遍历”来理解上段话,看是否符合以上定义。
首先“多次”肯定就满足了上述反复执行,从上文指定迭代的次数也可以看出迭代是有一定次数的。再者,如果要实现遍历,你要遍及每一个元素肯定就需要一定的顺序,不然就会导致有的读了多次,有的没读。所以遍历也就满足了上述的 每次迭代的顺序都是实现定义好的。其三,遍历的元素肯定是有限的,所以也满足通常会有明确的终止条件。
但是把迭代直接当成多次遍历其实也不妥,有的迭代方式不一定要访问所有元素呀。所以多次遍历只是迭代的一个子集。说成多次遍历是因为大多数时候我们说做迭代也是指做遍历。如果要准确地描述迭代,我们可以理解成重复多次地按照一定顺序访问元素。

2.为什么要引入迭代器以及抽象意义上的迭代器

比如我们要迭代数组,或者说遍历一个数组,我们需要知道两件事:1.按照什么顺序依次访问。 2.如何对一个元素进行访问。 数组很好办到,索引从0到数组长度-1依次访问,并且通过[index]就可以实现访问。但这不是一种通用的方法,因为并不是所有数据结构都具有顺序,也不是所有数据结构都能用索引下标访问。所以需要一个通用的工具来实现迭代。这个工具不仅封装了对数据结构的进行遍历的功能,并且他是通用的,提供了统一的使用接口,这样不同的使用者不用区分这是哪个数据结构的工具。这里所说的工具就是迭代器。其实这也就是红宝书中7.2迭代器模式所提及的:这种概念上的分离正是iterable和iterator的强大之处。现在你不用为写方法遍历发愁了,我写好了一个专门的通用工具给你,只要你使用这个工具的一个接口就可以迭代了,虽然不同的数据结构我为你提供的工具不同,但提供的工具都有这个接口,只要用这个接口就行了,你也不用为了适配不同的数据结构还要去写不同的方法了。

3.可迭代对象:

还是看一段红宝书的原话:

实现iterable接口要求同时具备两种能力:支持迭代的自我识别能力和创建实现Iterator接口的对象的能力。在ECMAScript中,这意味着必须暴露一个属性作为“默认迭代器”,而且这个属性必须使用特殊的Symbol.iterator作为键。这个默认迭代器属性必须引用一个迭代器工厂函数,调用这个工厂函数必须返回一个新迭代器。

这句话看完你可能有点懵,没事,我给你翻译一下:也就是说,你要让你的对象是可迭代对象,那么你必须给你的对象添加一个[Symbol.iterator]属性,属性值是工厂函数,工厂函数负责返回一个迭代器。所以可迭代对象就是 1.实现了迭代器功能的对象,也就是上文所说的支持迭代的自我识别能力,迭代器不就有这个能力吗。2.实现了创建迭代器对象的功能,具体通过给[Symbol.iterator]属性添加一个工厂函数创建,这个工厂函数进行创建。也就是上文的创建实现Iterator接口的对象的能力。

4.迭代器

这里直接通过红宝书的例子来带你具体看看什么是迭代器,并且也具体化解释了上文的可迭代对象。

class Counter {
    
    
	constructor(limit) {
    
    
		this.count = 1;
		this.limit = limt;
	}
	next() {
    
    
		if (this.count <= this.limit) {
    
    
			return {
    
     done: false, value: this.count++ };
		} else {
    
    
			return {
    
     done: true, value: undefined };
		}
	}
	[symbol.iterator]() {
    
    
		return this;
	}
}

前文说过:必须给你的对象添加一个[Symbol.iterator]属性,属性值是工厂函数,工厂函数负责返回一个迭代器。我们看例子中的[symbol.iterator]属性,返回的是本身,也就是说本身就是一个迭代器。也就是我们所说的迭代工具,而迭代工具要满足提供一个封装好的迭代接口,就是上面的next接口。

ps:这篇文章只是为了琳琳才写

猜你喜欢

转载自blog.csdn.net/weixin_43406295/article/details/115444133