迭代器
Iterator
对象是通过提供返回迭代器结果对象的 next()
方法来符合 迭代器协议 的对象。所有内置迭代器都继承自 Iterator
类。Iterator
类提供了一个 [Symbol.iterator]()
方法,该方法返回迭代器对象本身,使迭代器也成为 iterable。它还提供了一些使用迭代器的辅助方法。
¥An Iterator
object is an object that conforms to the iterator protocol by providing a next()
method that returns an iterator result object. All built-in iterators inherit from the Iterator
class. The Iterator
class provides a [Symbol.iterator]()
method that returns the iterator object itself, making the iterator also iterable. It also provides some helper methods for working with iterators.
描述
¥Description
以下都是内置的 JavaScript 迭代器:
¥The following are all built-in JavaScript iterators:
Array.prototype.values()
、Array.prototype.keys()
、Array.prototype.entries()
、Array.prototype[Symbol.iterator]()
、TypedArray.prototype.values()
、TypedArray.prototype.keys()
、TypedArray.prototype.entries()
、TypedArray.prototype[Symbol.iterator]()
和arguments[Symbol.iterator]()
返回的数组迭代器。String.prototype[Symbol.iterator]()
返回的字符串迭代器。Map.prototype.values()
、Map.prototype.keys()
、Map.prototype.entries()
和Map.prototype[Symbol.iterator]()
返回的映射迭代器。Set.prototype.values()
、Set.prototype.keys()
、Set.prototype.entries()
和Set.prototype[Symbol.iterator]()
返回的 Set Iterator。RegExp.prototype[Symbol.matchAll]()
和String.prototype.matchAll()
返回的正则表达式字符串迭代器。- 生成器函数 返回的
Generator
对象。 - 由
Intl.Segmenter.prototype.segment()
返回的Segments
对象的[Symbol.iterator]()
方法返回的 Segments Iterator。 - 由迭代器辅助程序方法(例如
Iterator.prototype.filter()
和Iterator.prototype.map()
)返回的迭代器辅助程序。
每个迭代器都有一个不同的原型对象,它定义特定迭代器使用的 next()
方法。例如,所有字符串迭代器对象都继承自隐藏对象 StringIteratorPrototype
,该对象具有按代码点迭代此字符串的 next()
方法。StringIteratorPrototype
还有一个 [Symbol.toStringTag]
属性,其初始值为字符串 "String Iterator"
。该属性在 Object.prototype.toString()
中使用。同样,其他迭代器原型也有自己的 [Symbol.toStringTag]
值,与上面给出的名称相同。
¥Each of these iterators have a distinct prototype object, which defines the next()
method used by the particular iterator. For example, all string iterator objects inherit from a hidden object StringIteratorPrototype
, which has a next()
method that iterates this string by code points. StringIteratorPrototype
also has a [Symbol.toStringTag]
property whose initial value is the string "String Iterator"
. This property is used in Object.prototype.toString()
. Similarly, other iterator prototypes also have their own [Symbol.toStringTag]
values, which are the same as the names given above.
所有这些原型对象都继承自 Iterator.prototype
,Iterator.prototype
提供了返回迭代器对象本身的 [Symbol.iterator]()
方法,使得迭代器也是 iterable。
¥All of these prototype objects inherit from Iterator.prototype
, which provides a [Symbol.iterator]()
method that returns the iterator object itself, making the iterator also iterable.
迭代器助手
¥Iterator helpers
注意:这些方法是迭代器助手,而不是可迭代助手,因为对象可迭代的唯一要求就是存在
[Symbol.iterator]()
方法。没有可安装这些方法的共享原型。¥Note: These methods are iterator helpers, not iterable helpers, because the only requirement for an object to be iterable is just the presence of a
[Symbol.iterator]()
method. There is no shared prototype to install these methods on.
Iterator
类本身提供了一些用于使用迭代器的辅助方法。例如,你可能想做以下事情:
¥The Iterator
class itself provides some helper methods for working with iterators. For example, you may be tempted to do the following:
const nameToDeposit = new Map([
["Anne", 1000],
["Bert", 1500],
["Carl", 2000],
]);
const totalDeposit = [...nameToDeposit.values()].reduce((a, b) => a + b);
首先将 Map.prototype.values()
返回的迭代器转换为数组,然后使用 Array.prototype.reduce()
方法计算总和。但是,这会创建一个中间数组并迭代该数组两次。相反,你可以使用迭代器本身的 reduce()
方法:
¥This first converts the iterator returned by Map.prototype.values()
to an array, then uses the Array.prototype.reduce()
method to calculate the sum. However, this both creates an intermediate array and iterates the array twice. Instead, you can use the reduce()
method of the iterator itself:
const totalDeposit = nameToDeposit.values().reduce((a, b) => a + b);
这种方法更加高效,因为它只迭代迭代器一次,而不需要记住任何中间值。迭代器辅助方法对于使用无限迭代器是必需的:
¥This method is more efficient, because it only iterates the iterator once, without memorizing any intermediate values. Iterator helper methods are necessary to work with infinite iterators:
function* fibonacci() {
let current = 1;
let next = 1;
while (true) {
yield current;
[current, next] = [next, current + next];
}
}
const seq = fibonacci();
const firstThreeDigitTerm = seq.find((n) => n >= 100);
你无法将 seq
转换为数组,因为它是无限的。相反,你可以使用迭代器本身的 find()
方法,该方法仅根据需要迭代 seq
以找到满足条件的第一个值。
¥You cannot convert seq
to an array, because it is infinite. Instead, you can use the find()
method of the iterator itself, which only iterates seq
as far as necessary to find the first value that satisfies the condition.
你会发现许多迭代器方法类似于数组方法,例如:
¥You will find many iterator methods analogous to array methods, such as:
Iterator.prototype.drop()
和 Iterator.prototype.take()
组合起来有点类似于 Array.prototype.slice()
。
¥Iterator.prototype.drop()
and Iterator.prototype.take()
combined are somewhat analogous to Array.prototype.slice()
.
其中,filter()
、flatMap()
、map()
、drop()
和 take()
返回一个新的 Iterator Helper 对象。迭代器助手也是一个 Iterator
实例,使得助手方法可链接。所有迭代器辅助对象都继承自一个公共原型对象,该对象实现了迭代器协议:
¥Among these methods, filter()
, flatMap()
, map()
, drop()
, and take()
return a new Iterator Helper object. The iterator helper is also an Iterator
instance, making the helper methods chainable. All iterator helper objects inherit from a common prototype object, which implements the iterator protocol:
迭代器助手与底层迭代器共享相同的数据源,因此迭代迭代器助手会导致底层迭代器也被迭代。没有办法对迭代器进行 "fork" 来允许它被迭代多次。
¥The iterator helper shares the same data source as the underlying iterator, so iterating the iterator helper causes the underlying iterator to be iterated as well. There is no way to "fork" an iterator to allow it to be iterated multiple times.
const it = [1, 2, 3].values();
const it2 = it.drop(0); // Essentially a copy
console.log(it.next().value); // 1
console.log(it2.next().value); // 2
console.log(it.next().value); // 3
适当的迭代器
¥Proper iterators
"iterators" 有两种:符合 迭代器协议 的对象(至少只需要存在 next()
方法),以及从 Iterator
类继承的对象,它们使用辅助方法。它们并不相互蕴涵 - 从 Iterator
继承的对象不会自动成为迭代器,因为 Iterator
类没有定义 next()
方法。相反,该对象需要自己定义一个 next()
方法。正确的迭代器是既符合迭代器协议又继承自 Iterator
的迭代器,并且大多数代码期望迭代器是正确的迭代器并且可迭代器返回正确的迭代器。要创建正确的迭代器,请定义一个扩展 Iterator
的类,或使用 Iterator.from()
方法。
¥There are two kinds of "iterators": objects that conform to the iterator protocol (which, at its minimum, only requires the presence of a next()
method), and objects that inherit from the Iterator
class, which enjoy the helper methods. They do not entail each other — objects that inherit from Iterator
do not automatically become iterators, because the Iterator
class does not define a next()
method. Instead, the object needs to define a next()
method itself. A proper iterator is one that both conforms to the iterator protocol and inherits from Iterator
, and most code expect iterators to be proper iterators and iterables to return proper iterators. To create proper iterators, define a class that extends Iterator
, or use the Iterator.from()
method.
class MyIterator extends Iterator {
next() {
// …
}
}
const myIterator = Iterator.from({
next() {
// …
},
});
构造函数
静态方法
实例属性
¥Instance properties
这些属性在 Iterator.prototype
上定义并由所有 Iterator
实例共享。
¥These properties are defined on Iterator.prototype
and shared by all Iterator
instances.
Iterator.prototype.constructor
-
创建实例对象的构造函数。对于
Iterator
实例,初始值为Iterator
构造函数。 Iterator.prototype[Symbol.toStringTag]
-
[Symbol.toStringTag]
属性的初始值为字符串"Iterator"
。该属性在Object.prototype.toString()
中使用。注意:与大多数内置类上的
[Symbol.toStringTag]
不同,出于 Web 兼容性原因,Iterator.prototype[Symbol.toStringTag]
是可写的。¥Note: Unlike the
[Symbol.toStringTag]
on most built-in classes,Iterator.prototype[Symbol.toStringTag]
is writable for web compatibility reasons.
实例方法
¥Instance methods
Iterator.prototype.drop()
Experimental-
返回一个新的迭代器助手,该助手会在此迭代器开头跳过给定数量的元素。
Iterator.prototype.every()
Experimental-
测试迭代器生成的所有元素是否通过所提供函数实现的测试。
Iterator.prototype.filter()
Experimental-
返回一个新的迭代器辅助程序,它仅生成提供的回调函数返回
true
的迭代器元素。 Iterator.prototype.find()
Experimental-
返回迭代器产生的第一个满足所提供的测试函数的元素。如果没有值满足测试函数,则返回
undefined
。 Iterator.prototype.flatMap()
Experimental-
返回一个新的迭代器辅助程序,它获取原始迭代器中的每个元素,通过映射函数运行它,并生成映射函数返回的元素(包含在另一个迭代器或可迭代器中)。
Iterator.prototype.forEach()
Experimental-
对迭代器生成的每个元素执行一次提供的函数。
Iterator.prototype.map()
Experimental-
返回一个新的迭代器助手,它生成迭代器的元素,每个元素都由映射函数转换。
Iterator.prototype.reduce()
Experimental-
对迭代器生成的每个元素执行用户提供的 "reducer" 回调函数,并传入前一个元素计算的返回值。在所有元素上运行减速器的最终结果是一个值。
Iterator.prototype.some()
Experimental-
测试迭代器中的至少一个元素是否通过所提供函数实现的测试。它返回一个布尔值。
Iterator.prototype.take()
Experimental-
返回一个新的迭代器助手,该迭代器助手在此迭代器中生成给定数量的元素,然后终止。
Iterator.prototype.toArray()
Experimental-
创建一个新的
Array
实例,其中填充了迭代器生成的元素。 Iterator.prototype[Symbol.iterator]()
-
返回迭代器对象本身。这允许迭代器对象也是可迭代的。
示例
将迭代器用作可迭代对象
规范
Specification |
---|
ECMAScript Language Specification # sec-%iteratorprototype%-object |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also