经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
es6 快速入门 系列 —— 迭代器 (Iterator) 和 生成器 (Generator)
来源:cnblogs  作者:彭加李  时间:2021/3/1 9:13:34  对本文有异议

其他章节请看:

es6 快速入门 系列

迭代器 (Iterator) 和 生成器 (Generator)

试图解决的问题

  1. let colors = ['red', 'blue', 'green', 'yellow']
  2. for(let i = 0, len = colors.length; i < len; i++){
  3. console.log(colors[i])
  4. }

上面是一段标准的 for 循环代码,变过变量 i 来跟踪 colors 的索引,虽然语法简单,但如果将多个循环嵌套则需要跟踪多个变量,代码复杂度会大增,一不小心就错误的使用了其他 for 循环的跟踪变量,导致程序出错。迭代器的出现旨在消除这种复杂性并减少循环中的错误

解决的方法

使用迭代器优化上述问题,请看代码:

  1. let colors = ['red', 'blue', 'green', 'yellow']
  2. for(let color of colors){
  3. console.log(color) // 依次输出:red blue green yellow
  4. }

每个集合(数组、Map和Set)类型都有一个默认的迭代器,在 for-of 循环中,如果没有显示指定则使用默认迭代器

关于迭代器是什么,生成器是什么,这里的数组、for-of和迭代器三者之间的关系又是什么,

所有这些疑问都能在下面的补充章节中找到解答

补充

什么是迭代器

下面我们用 es5 创建一个迭代器:

  1. function createIterator(items){
  2. let i = 0;
  3. let len = items.length;
  4. return {
  5. next: function(){
  6. const result = {
  7. value: items[i],
  8. done: i++ >= len
  9. }
  10. return result;
  11. }
  12. }
  13. }
  14. let iterator = createIterator(['a', 'b', 'c'])
  15. console.log(iterator.next()) // { value: 'a', done: false }
  16. console.log(iterator.next()) // { value: 'b', done: false }
  17. console.log(iterator.next()) // { value: 'c', done: true }
  18. console.log(iterator.next()) // { value: undefined, done: true }

迭代器是一个特殊的对象,它有专门为迭代过程而设计的专有接口,所有的迭代器都有 next() 方法,每次调用 next() 都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,是一个布尔值类型的值,当没有更多返回数据时返回true

上面这个示例很复杂,es6 中迭代器的编写规则也很复杂,所以 es6 引入生成器,让创建迭代器的过程变得简单

什么是生成器

生成器是一种返回迭代器的函数。通过 function 关键字后面的星号(*)来表示,函数中会用到新的关键字 yield

下面我们用生成器重写上面的 createIterator() 方法:

  1. // 星号* 可以紧挨着 function 关键字,也可以在中间加空格
  2. function *createIterator(items){
  3. for(let i = 0, len = items.length; i < len; i++){
  4. yield items[i]
  5. }
  6. }
  7. let iterator = createIterator(['a', 'b', 'c'])
  8. console.log(iterator.next()) // { value: 'a', done: false }
  9. console.log(iterator.next()) // { value: 'b', done: false }
  10. console.log(iterator.next()) // { value: 'c', done: false }
  11. console.log(iterator.next()) // { value: undefined, done: true }

createIterator()前面的星号表明它是一个生成器;yield 是 es6 中的新特性,可以通过它来指定调用迭代器的 next() 方法时的返回值和返回顺序。

生成器最有趣的大概是,每次执行完 yield 语句后,函数会自动停止执行。

yield只能在生成器内部使用。下面例子中,从字面上看,yield 确实是在生成器内部,但是它与 return 一样,二者都不能穿透函数边界。

  1. function *createIterator(items){
  2. items.forEach(function(){
  3. yield 1 // 报错
  4. })
  5. }

:不能用箭头函数创建生成器

可迭代对象和 for-of 循环

首先来回答上面遗留的问题:数组、for-of 和迭代器三者之间的关系是什么?

  1. let colors = ['red', 'blue', 'green', 'yellow']
  2. for(let color of colors){
  3. console.log(color) // 依次输出:red blue green yellow
  4. }

es6中,所有的集合(数组、Map及Set)和字符串都是可迭代对象。一个对象如果有与之对应的迭代器,那么它就是可迭代对象;for-of 循环每执行一次都会调用可迭代对象的 next() 方法,并将迭代器返回的结果对象中的 value 存储在一个变量中,循环将持续到返回对象的 done 属性的值为 true。

三者之间的关系这就很清楚了,数组有自己的迭代器,for-of 会循环迭代器

es6中的可迭代对象具有 Symbol.iterator 属性,执行 Symbol.iterator 指定的函数会返回一个作用于该对象的迭代器,以数组为例:

  1. let arr = [11, 22]
  2. let iterator = arr[Symbol.iterator]()
  3. console.log(iterator.next()) // { value: 11, done: false }
  4. console.log(iterator.next()) // { value: 22, done: false }
  5. console.log(iterator.next()) // { value: undefined, done: true }

:如果将 for-of 语句用于不可迭代对象、null 或 undefined 将会导致程序报错

内建迭代器

为了更好的访问数据,es6给数组、Set和Map都内建了以下三种迭代器:

  1. entries() 返回一种迭代器,其值为多个键值对
  2. values() 返回一种迭代器,其值为集合的所有值
  3. keys() 返回一种迭代器,其值为集合的所有键名
  1. let arr = [11, 22]
  2. for(let entry of arr.entries()){
  3. // 依次输出:[ 0, 11 ] [ 1, 22 ]
  4. console.log(entry)
  5. }
  6. for(let key of arr.keys()){
  7. // 依次输出:0 1
  8. console.log(key)
  9. }

每种集合都有一个默认的迭代器,在 for-of 循环中,如果没有显示指定则使用默认的迭代器。数组和 Set 的默认迭代器是 values() 方法,Map 的默认迭代器是 entries() 方法

  1. let arr = [11, 22]
  2. for(let value of arr.values()){
  3. // 依次输出:11 22
  4. console.log(value)
  5. }
  6. // 等同于
  7. let arr = [11, 22]
  8. for(let value of arr){
  9. // 依次输出:11 22
  10. console.log(value)
  11. }

自从 es6 添加了迭代器,DOM 中的 NodeList 类型也拥有的默认迭代器,其行为与数组的默认迭代器完全一致

其他章节请看:

es6 快速入门 系列

原文链接:http://www.cnblogs.com/pengjiali/p/14457239.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号