while
循环迭代可迭代对象同步迭代是一种_协议_(接口以及使用它们的规则),它连接了 JavaScript 中的两组实体
**数据源:** 一方面,数据有多种形式和大小。在 JavaScript 的标准库中,您有线性数据结构数组、有序集合 Set(元素按添加时间排序)、有序字典 Map(条目按添加时间排序)等等。在库中,您可能会发现树形数据结构等等。
**数据消费者:** 另一方面,您有一整类结构和算法,它们只需要_顺序_访问其输入:一次一个值,直到访问完所有值。例子包括 for-of
循环和通过 ...
展开到函数调用中。
迭代协议通过接口 Iterable
连接这两组:数据源“通过它”顺序地传递其内容;数据消费者通过它获取其输入。
图 18 说明了迭代的工作原理:数据消费者使用接口 Iterable
;数据源实现它。
JavaScript 实现接口的方式
在 JavaScript 中,如果一个对象具有它描述的所有方法,则该对象_实现_了一个接口。本章提到的接口仅存在于 ECMAScript 规范中。
数据源和数据消费者都从这种安排中获益
如果您开发新的数据结构,您只需要实现 Iterable
,就可以立即将大量工具应用于它。
如果您编写的代码使用迭代,它会自动与许多数据源一起工作。
两个角色(由接口描述)构成了迭代的核心(图 19)
这些是迭代协议接口的类型定义(使用 TypeScript 的符号)
interface Iterable<T> {
Symbol.iterator]() : Iterator<T>;
[
}
interface Iterator<T> {
next() : IteratorResult<T>;
}
interface IteratorResult<T> {
: T;
value: boolean;
done }
接口的使用方式如下
Symbol.iterator
的方法向 Iterable
请求迭代器。Iterator
通过其方法 .next()
返回迭代值。.value
是迭代值。.done
指示迭代是否已到达末尾。它在最后一个迭代值之后为 true
,之前为 false
。这是使用迭代协议的示例
const iterable = ['a', 'b'];
// The iterable is a factory for iterators:
const iterator = iterable[Symbol.iterator]();
// Call .next() until .done is true:
.deepEqual(
assert.next(), { value: 'a', done: false });
iterator.deepEqual(
assert.next(), { value: 'b', done: false });
iterator.deepEqual(
assert.next(), { value: undefined, done: true }); iterator
while
循环迭代可迭代对象以下代码演示了如何使用 while
循环迭代可迭代对象
function logAll(iterable) {
const iterator = iterable[Symbol.iterator]();
while (true) {
const {value, done} = iterator.next();
if (done) break;
console.log(value);
}
}
logAll(['a', 'b']);
// Output:
// 'a'
// 'b'
练习:手动使用同步迭代
exercises/sync-iteration-use/sync_iteration_manually_exrc.mjs
我们已经看到了如何手动使用迭代协议,它相对繁琐。但该协议并非旨在直接使用——它旨在通过构建在其之上的更高级别的语言结构来使用。本节展示了它的外观。
JavaScript 的数组是可迭代的。这使我们能够使用 for-of
循环
const myArray = ['a', 'b', 'c'];
for (const x of myArray) {
console.log(x);
}// Output:
// 'a'
// 'b'
// 'c'
通过数组模式进行解构(稍后解释)也在底层使用了迭代
const [first, second] = myArray;
.equal(first, 'a');
assert.equal(second, 'b'); assert
JavaScript 的 Set 数据结构是可迭代的。这意味着 for-of
可以工作
const mySet = new Set().add('a').add('b').add('c');
for (const x of mySet) {
console.log(x);
}// Output:
// 'a'
// 'b'
// 'c'
数组解构也是如此
const [first, second] = mySet;
.equal(first, 'a');
assert.equal(second, 'b'); assert
以下内置数据源是可迭代的
要迭代对象的属性,您需要使用 Object.keys()
和 Object.entries()
等辅助函数。这是必要的,因为属性存在于独立于数据结构级别的不同级别。
本节列出了使用同步迭代的结构。
通过数组模式进行解构
const [x,y] = iterable;
通过 ...
展开到函数调用和数组字面量中
func(...iterable);
const arr = [...iterable];
for-of
循环
for (const x of iterable) { /*···*/ }
yield*
:
function* generatorFunction() {
yield* iterable;
}
const obj = Object.fromEntries(iterableOverKeyValuePairs);
const arr = Array.from(iterable);
const m = new Map(iterableOverKeyValuePairs);
const wm = new WeakMap(iterableOverKeyValuePairs);
const s = new Set(iterableOverElements);
const ws = new WeakSet(iterableOverElements);
Promise 组合器函数:Promise.all()
等。
const promise1 = Promise.all(iterableOverPromises);
const promise2 = Promise.race(iterableOverPromises);
const promise3 = Promise.any(iterableOverPromises);
const promise4 = Promise.allSettled(iterableOverPromises);
测验
参见 测验应用程序。