跳到主要内容

JavaScript 迭代器和可迭代对象

提示
  1. JavaScript 可迭代对象和迭代器:可迭代对象是具有 Symbol.iterator 方法的数据结构,如数组或字符串。迭代器是由可迭代对象的 Symbol.iterator() 方法返回的对象,用于通过 next() 方法逐个访问对象的元素。
  2. 使用 for...of 遍历可迭代对象for...of 循环可用于直接遍历可迭代对象,如数组或字符串,自动调用迭代器的 next() 方法。
  3. next() 方法和自定义迭代器next() 方法返回包含 value(当前元素值)和 done(迭代是否完成的布尔值)的对象。用户可以创建自定义迭代器,提供特定逻辑来逐个返回序列中的元素。

JavaScript 提供了一种协议来迭代数据结构。此协议定义了如何使用 for...of 循环迭代这些数据结构。

该协议的概念可以分为:

  • 可迭代对象
  • 迭代器

可迭代协议提到可迭代对象应该有 Symbol.iterator 键。

JavaScript 可迭代对象

具有 Symbol.iterator() 方法的数据结构称为可迭代对象。例如,数组、字符串、集合等。

JavaScript 迭代器

迭代器是由 Symbol.iterator() 方法返回的对象。

迭代器协议提供了 next() 方法来一次访问一个可迭代对象(数据结构)的每个元素。

让我们看一个有 Symbol.Iterator() 的可迭代对象的例子:

const arr = [1, 2, 3];

// 调用 Symbol.iterator() 方法
const arrIterator = arr[Symbol.iterator]();

// 得到数组迭代器
console.log(arrIterator);

const str = "hello";

// 调用 Symbol.iterator() 方法
const strIterator = str[Symbol.iterator]();

// 得到字符串迭代器
console.log(strIterator);

输出

Array Iterator {}
StringIterator {}

这里,调用数组和字符串的 Symbol.iterator() 方法返回各自的迭代器。

遍历可迭代对象

你可以使用 for...of 循环来遍历这些可迭代对象。你可以像这样通过 Symbol.iterator() 方法进行迭代:

const number = [1, 2, 3];

for (let n of number[Symbol.iterator]()) {
console.log(n);
}

输出

1;
2;
3;

或者你可以直接这样遍历数组:

const number = [1, 2, 3];

for (let n of number) {
console.log(n);
}

这里,迭代器允许 for...of 循环遍历数组并返回每个值。

JavaScript next() 方法

迭代器对象有一个 next() 方法,它返回序列中的下一个项目。

next() 方法包含两个属性:valuedone

  • value value 属性可以是任何数据类型,并表示序列中的当前值。
  • done done 属性是一个布尔值,指示迭代是否完成。如果迭代未完成,done 属性设置为 false,否则设置为 true

让我们看一个数组可迭代对象的例子:

const arr = ["h", "e", "l", "l", "o"];

let arrIterator = arr[Symbol.iterator]();

console.log(arrIterator.next()); // {value: "h", done: false}
console.log(arrIterator.next()); // {value: "e", done: false}
console.log(arrIterator.next()); // {value: "l", done: false}
console.log(arrIterator.next()); // {value: "l", done: false}
console.log(arrIterator.next()); // {value: "o", done: false}
console.log(arrIterator.next()); // {value: undefined, done: true}

你可以反复调用 next() 来迭代 arrIterator 对象。

  • next() 方法返回一个包含两个属性:valuedone 的对象。
  • next() 方法到达序列的末尾时,done 属性设置为 false

让我们看看 for...of 循环如何执行上述程序。例如,

const arr = ["h", "e", "l", "l", "o"];

for (let i of arr) {
console.log(i);
}

输出

h;
e;
l;
l;
o;

for...of 循环与上述程序做的完全相同。

for...of 循环不断地调用迭代器上的 next() 方法。一旦到达 done:truefor...of 循环终止。

用户定义的迭代器

你还可以创建自己的迭代器,并调用 next() 访问下一个元素。例如,

function displayElements(arr) {
// 更新迭代
let n = 0;

return {
// 实现 next() 函数
next() {
if (n < arr.length) {
return {
value: arr[n++],
done: false,
};
}

return {
value: undefined,
done: true,
};
},
};
}

const arr = ["h", "e", "l", "l", "o"];

const arrIterator = displayElements(arr);

console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());

输出

{value: "h", done: false}
{value: "e", done: false}
{value: "l", done: false}
{value: "l", done: false}
{value: "o", done: false}
{value: undefined, done: true}

在上述程序中,我们创建了自己的迭代器。displayElements() 函数返回 valuedone 属性。

  • 每次调用 next() 方法时,函数执行一次并显示数组的值。
  • 最终,当数组的所有元素都用尽时,done 属性设置为 truevalueundefined