ES6 迭代器:Iterator, Iterable 和 Generator
栏目: JavaScript · 发布时间: 6年前
内容简介:对集合中每个元素进行处理是很常见的操作,比如数组遍历、对象的属性遍历。 以往这些操作是通过本文展开介绍了这些相关概念:Iterables(可迭代对象)、Iterator(迭代器)、 Generator(生成器)和 Generator Function(生成器函数), 以及相关机制:Iterable Protocol、Iterator Protocol、Symbol.iterator。实现了 Iterable Protocol 的对象称为
对集合中每个元素进行处理是很常见的操作,比如数组遍历、对象的属性遍历。
以往这些操作是通过 for
循环、 .forEach
、 .map
等方式进行,
在 ES6
中直接把迭代放在语言层面进行支持,同时提供定制 for...of
的机制。
借由迭代器机制为 Map、Array、String 等对象提供了统一的遍历语法,以及更方便的相互转换。
为方便编写迭代器还提供了生成器(Generator)语法。
本文展开介绍了这些相关概念:Iterables(可迭代对象)、Iterator(迭代器)、 Generator(生成器)和 Generator Function(生成器函数), 以及相关机制:Iterable Protocol、Iterator Protocol、Symbol.iterator。
Iterables 和 Iterators
实现了 Iterable Protocol 的对象称为 可迭代对象(Iterables)
,这种对象可以用 for...of
来遍历。 Map
, Set
, Array, String 都属于可迭代对象。
自定义的对象也可以使用这一机制,成为可迭代对象。
Iterable Protocol:需要实现一个 ECMA @@iterator
方法,即在键 [Symbol.iterator]
上提供一个方法。对象被 for...of
调用时,这个方法会被调用。方法应该返回一个迭代器对象(Iterator)用来迭代。
实现了 Iterator Protocol 的对象称为 迭代器对象(Iterator) ,也就是我们说的迭代器对象。
Iterator Protocol:又称 Iteration Protocol,需要实现一个 next()
方法,每次调用会返回一个包含 value
(当前指向的值)和 done
(是否已经迭代完成)的对象。
标准 Iterables 举例:Array
Array 可以用 for...of
来遍历,是一个可迭代对象。
我们来观察它是如何实现上述 Protocol 的。首先拿到它的 Symbol.iterator
属性(Iterable Protocol):
let arr = ['Alice', 'Bob', 'Carol'] let iterator = arr[Symbol.iterator]()
然后调用它的 .next()
方法(Iterator Protocol)得到,直到 done === true
:
console.log(iterator.next()) // { value: 'Alice', done: false } console.log(iterator.next()) // { value: 'Bob', done: false } console.log(iterator.next()) // { value: 'Carol', done: false } console.log(iterator.next()) // { value: undefined, done: true }
自定义 Iterables
除了 Array、Map 等标准的全局对象外,我们的自定义对象也可以通过提供一个 Symbol.iterator
成为 Iteratable。
比如实现一个 50 以内的 斐波那契数列
:
let obj = { [Symbol.iterator]: function () { let a = 0, b = 0 return { next: function () { let value = 0 if (!a) { value = a = 1 } else if (!b) { value = b = 1 } else if (b < 50){ value = a + b a = b b = value } return {done: value === 0, value} } } } } for (let i of obj) { console.log(i) // 1 1 2 3 5 8 13 21 34 55 }
利用 Generator
上述迭代器中我们维护了 a
和 b
两个状态,以及每次调用进入的条件分支。
ES6 提供了 Generator Function
(生成器方法)来方便上述迭代器的实现。
生成器方法返回的 Generator 对象
直接就是一个实现了 Iterator Protocol 的对象。
下面使用生成器方法重新实现50以内的斐波那契数列:
let obj = { [Symbol.iterator]: function *() { let a = 1, b = 1 yield a yield b while (b < 50) { yield b = a + b a = b - a } } } for (let i of obj) { console.log(i) // 1 1 2 3 5 8 13 21 34 55 }
Map, Set, String, Array 互相转换
Iteration Protocol 给出了统一的迭代协议,使得不同类型的集合间转换更加方便,也方便了编写适用于不同类型集合的算法。 这一概念类似 Lodash 中的 Collection, 或者STL 中的迭代器。以下是一些很方便的转换技巧:
从 Array
生成 Set
,可用于数组去重:
new Set(['Alice', 'Bob', 'Carol']) // {'Alice', 'Bob', 'Carol'} // 等价于 new Set(['Alice', 'Bob', 'Carol'][Symbol.iterator]())
从 Set
得到 Array
:
let set = new Set(['Alice', 'Bob', 'Carol']) Array.from(set) // 'Alice', 'Bob', 'Carol' // 等价于 Array.from(set[Symbol.iterator]())
除了 for...of
外, 展开语法
(Spread Syntax) ...
也支持迭代器(Iterables)。借此可以简写作:
let set = new Set(['Alice', 'Bob', 'Carol']) let names = [...set] // 'Alice', 'Bob', 'Carol'
从 String
到 Set
,得到字符串中包含的字符:
let alphabet = 'abcdefghijklmnopqrstuvwxyz'; new Set(alphabet) // {'a', 'b', 'c', ...} // 等价于 new Set('alice bob'[Symbol.iterator]())
从 Object
到 Map
,也就是把传统的 JavaScript 映射转换为 Map
:
let mapping = { "foo": "bar" } new Map(Object.entries(mapping)) // {"foo" => "bar"}
类似地, Object
的键的集合可以这样获取:
let mapping = { "foo": "bar" } new Set(Object.keys(mapping)) // {"foo"}
参考链接
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
- https://www.ecma-international.org/ecma-262/6.0/#sec-iteration
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
以上所述就是小编给大家介绍的《ES6 迭代器:Iterator, Iterable 和 Generator》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 迭代器萃取与反向迭代器
- 浅谈python可迭代对象,迭代器
- 可迭代对象,迭代器(对象),生成器(对象)
- 终于把动态规划与策略迭代、值迭代讲清楚了
- 终于把动态规划与策略迭代、值迭代讲清楚了
- 搞清楚 Python 的迭代器、可迭代对象、生成器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
模糊数学基础及实用算法
李鸿吉编 / 科学出版社 / 2005-1 / 55.00元
本书开发了模糊数学常用的计算机程序,并以大量的算例系统地介绍了模糊数学的实用算法。本书可以作为模糊数学的应用程序包,在详细解释源代码的同时,对应用程序开发所用到的Visual Basic 6.0方法做了系统介绍,其目的是为读者做进一步的自主开发提供便利。本书所提供的源程序可以作为读者自主开发的素材。本书配有光盘,分章节提供程序源代码。 本书可以作为大专院校、培训班的教学参考书。对需......一起来看看 《模糊数学基础及实用算法》 这本书的介绍吧!