在 JavaScript 中,一个可迭代对象是一个在其原型中有 Symbol.iterator()
方法的对象。一些可迭代对象的例子包括数组、集合、映射、字符串等。Symbol.iterator()
方法返回一个包含 next()
方法的对象,称为迭代器。这里,next()
方法在每次调用时返回可迭代对象中的元素。
next()
方法
迭代器对象的 next()
方法返回一个包含以下两个键值对的对象:
-
-
done
—— 包含一个布尔值。如果所有可迭代对象的迭代都已完成,则包含 true
。否则,包含 false
。
示例
在下面的例子中,我们创建了一个数组并将数组迭代器存储在 iter
变量中。之后,我们使用迭代器对象的 next()
方法获取下一个值。
输出显示 next()
方法返回包含 value
和 done
属性的对象。最后一次迭代仅返回包含 done
属性的对象。
<html>
<head>
<title>JavaScript - 迭代器</title>
</head>
<body>
<p id="output"></p>
<script>
const output = document.getElementById("output");
const nums = [10, 72, 45];
const iter = nums[Symbol.iterator]();
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
</script>
</body>
</html>
输出:
{"value":10,"done":false}
{"value":72,"done":false}
{"value":45,"done":false}
{"done":true}
用户定义的迭代器
在上面的部分中,我们已经查看了 JavaScript 中迭代器的工作方式。Symbol.iterator()
方法返回包含 next()
方法的对象,而当我们执行 next()
方法时,它会返回一个对象。
因此,我们可以以同样的方式实现用户定义的迭代器。
示例
在下面的例子中,我们使用函数创建了一个自定义迭代器。该函数返回包含 next()
方法的对象。next()
方法从第 n
个索引返回数组元素和布尔值 false
,如果 n
小于数组长度。如果 n
大于或等于数组长度,则返回仅包含布尔值 true
的 done
属性的对象。
之后,我们使用 iter.next()
语法获取下一个数组元素。
<html>
<head>
<title>JavaScript - 用户定义的迭代器</title>
</head>
<body>
<p id="output"></p>
<script>
const output = document.getElementById("output");
function customIterator(chars) {
let n = 0;
return {
next() {
if (n < chars.length) {
return {
value: chars[n++],
done: false
}
}
return {
done: true
}
}
}
}
const chars = ['A', 'C', 'E'];
const iter = customIterator(chars);
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
output.innerHTML += JSON.stringify(iter.next()) + "<br>";
</script>
</body>
</html>
输出:
{"value":"A","done":false}
{"value":"C","done":false}
{"value":"E","done":false}
{"done":true}
{"done":true}
上述代码使用函数定义了迭代器。因此,你不能使用 for…of
循环与迭代器。让我们通过下面的例子学习使用对象定义迭代器。
示例
在下面的例子中,我们添加了一个作为 Symbol.iterator
键值的函数。该函数返回 next()
方法。next()
方法返回奇数。如果奇数值为 9,则通过返回 {done: true}
对象完成迭代。
在这里,我们使用对象创建了迭代器。所以,你可以使用 for…of
循环。该循环将自动执行迭代器的 next()
方法,并返回由 next()
方法返回的对象中的 value
属性的值。
<html>
<head>
<title>JavaScript - 用户定义的迭代器</title>
</head>
<body>
<p id="output"></p>
<script>
const output = document.getElementById("output");
oddNum = {};
oddNum[Symbol.iterator] = function () {
let p = -1;
done = false;
return {
next() {
p += 2;
if (p == 9) return { done: true };
return { value: p, done: done };
}
};
}
for (const odd of oddNum) {
output.innerHTML += odd + "<br>";
}
</script>
</body>
</html>
输出:
1
3
5
7
你应该在需要对可迭代对象的遍历进行定制时创建用户定义的迭代器。例如,遍历数组的交替元素,从迭代器获取偶数或奇数等。