如何理解迭代器(Iterator)和生成器(Generator)
所有的新概念并不是人们闲的没事想出来的,而是为了解决已有的某些问题才出现的。所以只要我们从历史的角度去看,就能更容易理解这些新概念!
什么是迭代器
我们在用循环语句迭代数据时,必须要初始化一个变量来记录每次迭代在数据集中的位置,比如说for
循环:
1 | const arr = ['red', 'green', 'blue'] |
在上面的代码中,我们就是通过变量i
来跟踪索引,我们通过观察i
来了解现在循环到数组中的第几个项了。
这个例子中的循环很简单,但是如果嵌套循环,则需要追踪多个变量,代码复杂度增加,就很容易出错。就像Promise
的出现是为了解决回调地域一样,迭代器的出现就是为了消除这种复杂性并减少循环的错误。
为了更好的理解迭代器的运行方式,我们先用 ES5 的语法写一个迭代器函数,代码如下:
1 | function createIterator(items) { |
其实这段代码已经给出了迭代器的定义:迭代器函数定义了一个next()
方法,这个方法执行后会返回一个对象,拥有value
和done
两个属性,value
告诉你下次执行时候的返回值,done
告诉你是否执行完了。
什么是生成器
生成器就是“能够返回一个迭代器函数的函数”。
上面的迭代器我们是自己定义的,比较麻烦,所以官方出了一个可以生成迭代器的函数,试着比较一下下面两段效果一样的代码:
1 | // 自定义迭代器 |
就是这么简洁好用!
还是上面那个例子,我们粘过来,不过这一次我们使用生成器函数:
1 | function* createIterator(items) { |
其中,function*
用来声明一个生成器,yield
是一个关键字。
yield
是啥?在调用迭代器的next()
方法时,遇到yield
就会暂停,然后返回迭代器的结果对象{ value: xx, done: xx }
。当我们再次调用生成器的next()
方法时,如果它还没执行到头(done 不为 true),那么他就会继续执行。
以上。