JavaScript - 用户定义的迭代器



JavaScript 中,可迭代对象是在对象原型中具有 Symbol.iterator() 方法的对象。可迭代的一些示例包括 array、set、map、string 等。Symbol.iterator() 方法返回一个包含 next() 方法的对象,称为迭代器。在这里,next() 方法在每次调用中返回 iterable 的元素。

next() 方法

iterator 对象的 next() 方法返回一个包含下面给出的两个键值对的对象。

  • value − value 键包含元素作为值。
  • done - done 键包含布尔值。如果 iterable 的所有迭代都已完成,则它包含 true。否则,它包含 false。

在下面的示例中,我们创建了数组并将数组迭代器存储在 'iter' 变量中。之后,我们使用迭代器对象的 next() 方法来获取下一个值。

输出显示 next() 方法返回包含 'value' 和 'done' 属性的对象。最后一次迭代仅返回包含 'done' 属性的对象。


<html>
<head>
	 	<title> JavaScript - Iterators </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() 方法的对象。如果 n 小于数组长度,则 next() 方法返回包含数组元素和第 n 个索引中的 false 布尔值的对象。如果 n 大于或等于数组的长度,则返回仅包含 'done' 属性和 'true' 布尔值的对象。

之后,我们使用 iter.next() 语法来获取下一个数组元素。


<html>
<head>
	 	<title> JavaScript - User defined iterators </title>
</head>
<body>
	 	<p id = "output"> </p>
	 	<script>
	 	 	 const output = document.getElementById("output");
	 	 	 function customIterator(chars) {
	 	 	 	 	// To track index
	 	 	 	 	let n = 0;
	 	 	 	 	return {
	 	 	 	 	 	 // next() method
	 	 	 	 	 	 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 - User defined iterators </title>
</head>
<body>
	 	<p id = "output"> </p>
	 	 <script>
	 	 	 	const output = document.getElementById("output");
	 	 	 	// Empty object
	 	 	 	oddNum = {};
	 	 	 	// Add iterator	
	 	 	 	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

当用户定义的迭代器需要在 iterable 的遍历中进行自定义时,您应该创建用户定义的迭代器。例如,遍历替代数组元素,从迭代器中获取偶数或奇数等。