其他章节请看:

es6 快速入门 系列

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

试图解决的问题

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

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

解决的方法

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

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

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

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

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

补充

什么是迭代器

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

function createIterator(items){
let i = 0;
let len = items.length;
return {
next: function(){
const result = {
value: items[i],
done: i++ >= len
}
return result;
}
}
}
let iterator = createIterator(['a', 'b', 'c']) console.log(iterator.next()) // { value: 'a', done: false }
console.log(iterator.next()) // { value: 'b', done: false }
console.log(iterator.next()) // { value: 'c', done: true }
console.log(iterator.next()) // { value: undefined, done: true }

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

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

什么是生成器

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

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

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

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

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

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

function *createIterator(items){
items.forEach(function(){
yield 1 // 报错
})
}

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

可迭代对象和 for-of 循环

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

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

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

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

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

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

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

内建迭代器

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

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

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

let arr = [11, 22]
for(let value of arr.values()){
// 依次输出:11 22
console.log(value)
} // 等同于 let arr = [11, 22]
for(let value of arr){
// 依次输出:11 22
console.log(value)
}

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

其他章节请看:

es6 快速入门 系列

迭代器 (Iterator) 和 生成器 (Generator)的更多相关文章

  1. ES6中的迭代器(Iterator)和生成器(Generator)

    前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...

  2. Python进阶内容(四)--- 迭代器(Iterator)与生成器(Generator)

    迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...

  3. TypeScript 迭代器(iterator)和生成器(generator)

    ⒈迭代器(iterator) 1.可迭代性 当一个对象实现了Symbol.iterator属性时,我们认为它是可迭代的. 一些内置的类型如 Array,Map,Set,String,Int32Arra ...

  4. ES6中的迭代器(Iterator)和生成器(Generator)(一)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

  5. [TimLinux] Python 迭代器(iterator)和生成器(generator)

    1. 可迭代对象 from collection import Iterable class Iterable(metaclass=ABCMeta): ... def __iter__(self): ...

  6. ES6中的迭代器(Iterator)和生成器(Generator)(二)

    一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...

  7. Python的迭代器(iterator)和生成器(constructor)

    一.迭代器(iterator) 1.迭代器的概述 在Python中,for循环可以用于Python中的任何类型,包括列表.元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器 迭代器 ...

  8. Day11 python高级特性-- 迭代器 Iterator

    直接可以作用于for循环的数据类型有以下几种:   •  集合数据类型:        list.tuple.dict.set.str   •  Generator:        生成器 和 带 y ...

  9. Python中生成器generator和迭代器Iterator的使用方法

    一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...

随机推荐

  1. C#遇见C++的江湖 不行!得不到就干掉

    C#  VS C++ C#代码遇见了非托管dll如何处理 问题:托管与非托管,兼容? 方法一:DllImport 托管调试助手 "PInvokeStackImbalance" Me ...

  2. 【论文研读】Sabir, Ekraam, et al. "Recurrent convolutional strategies for face manipulation detection in videos."&#160;Interfaces (GUI)&#160;3.1 (2019).

    #摘要 错误信息通过合成逼真的图像和视频进行传播这一严重问题,需要鲁棒的篡改检测方法来应对.尽管在检测静止图像上的面部篡改方面已付出了巨大的努力,但人们对于通过利用视频流中存在的时序信息,对视频中被篡 ...

  3. BZOJ2555 SubString【SAM + Link Cut Tree】

    BZOJ2555. SubString 要求在线询问一个串在原串中出现的次数,并且可以在原串末尾添加字符串 如果没有修改的话,考虑建出\(parent\)树之后统计每个\(endpos\)节点的\(r ...

  4. CodeForces - 948C (前缀和+二分)

    博客界面的小人搞不好导致无心写博客 题意:tyd非常喜欢玩雪,下雪下了n天,第i天她会堆一堆大小为Vi的雪堆,但因为天气原因,每堆雪会融化Ti,问每天总共融化了多少雪: 直接上代码+注释 1 #inc ...

  5. Codeforces Round #687 (Div. 2, based on Technocup 2021 Elimination Round 2) B. Repainting Street (枚举)

    题意:有\(n\)栋房子,每栋房子都有自己的颜色\(c_i\),你每次可以对连续的长度为\(k\)的区间改变任何房子的颜色,问最少多少次可以使得所有房子颜色相同. 题解:因为只有\(100\)中颜色, ...

  6. Educational Codeforces Round 97 (Rated for Div. 2) D. Minimal Height Tree (贪心)

    题意:有一个从根节点\(BFS\)得来的序列(每次\(bfs\)子节点的时候保证是升序放入队列的),现在让你还原树(没必要和之前相同),问能构造出的最小的树的深度. 题解:不看根节点,我们从第二个位置 ...

  7. 2015ACM/ICPC亚洲区沈阳站-重现赛 D - Pagodas

    题意:有\(n\)个数,开始给你两个数\(a\)和\(b\),每次找一个没出现过的数\(i\),要求满足\(i=j+k\)或\(i=j-k\),当某个人没有数可以选的时候判他输,问谁赢. 题解:对于\ ...

  8. Typora Themes自定义

    Typora Themes自定义 Typora 支持css样式,自定义主题十分方便,修改自己的css文件,再放入其themes文件夹,重启Typora,即可看到自定义主题. Typora 官网,自定义 ...

  9. VScode 相关

    1.F5运行py文件,打开terminal终端的时候总是弹出Powershell窗口,只能在powershell窗口中用命令行运行程序,实在很不方便. 解法:右键Powershell属性,取消使用旧版 ...

  10. 一篇文章图文并茂地带你轻松学会 HTML5 storage

    html5 storage api localStorage 和 sessionStorage 是 html5 新增的用来存储数据的对象,他们让我们可以以键值对的形式存储信息. 为什么要有 stora ...