可迭代对象和迭代器是相同的吗,还是它们有所不同?
从规范(链接)来看,一个可迭代对象是一个对象,比如说obj
,它具有一个obj[Symbol.iterator]
函数属性,当调用该函数时,返回一个对象,该对象包含一个next
方法,该方法可以返回一个{value: ___, done: ___}
对象:
function foo() {
let i = 0;
const wah = {
next: function() {
if (i <= 2) return { value: (1 + 2 * i++), done: false }
else return { value: undefined, done: true }
}
};
return wah; // wah is iterator
}
let bar = {} // bar is iterable
bar[Symbol.iterator] = foo;
console.log([...bar]); // [1, 3, 5]
for (a of bar) console.log(a); // 1 3 5 (in three lines)
以上代码中,bar
是可迭代对象,wah
是迭代器,next()
则是迭代器接口。
因此,可迭代对象和迭代器是不同的东西。
现在,我们来看一个生成器和迭代器的常见示例:
function* gen1() {
yield 1;
yield 3;
yield 5;
}
const iter1 = gen1();
console.log([...iter1]); // [1, 3, 5]
for (a of iter1) console.log(a); // nothing
const iter2 = gen1();
for (a of iter2) console.log(a); // 1 3 5 (in three lines)
console.log(iter1[Symbol.iterator]() === iter1); // true
在上面的例子中,gen1
是生成器,iter1
是迭代器,iter1.next()
会执行适当的操作。但是 iter1[Symbol.iterator]
提供的函数会返回一个函数,调用该函数会返回迭代器 iter1
,因此在这种情况下,iter1
同时是可迭代对象和迭代器?同时,iter1
与上面的示例1不同,因为示例1中的可迭代对象可以使用 [...bar]
无限次地提供 [1, 3, 5]
,而 iter1
是一个可迭代对象,但由于它返回自身,即相同的迭代器,因此只能一次性提供 [1, 3, 5]
。因此,我们可以说对于可迭代对象
bar
,[...bar]
可以多少次给出结果 [1, 3, 5]
,答案是取决于具体情况。可迭代对象和迭代器是否相同?答案是它们是不同的东西,但它们可以相同,当可迭代对象使用自身作为迭代器时是这样的。这个理解正确吗?
iter1
在这种情况下既是可迭代对象又是迭代器吗?”- 是的。所有本地迭代器也都是可迭代的,因为它们返回自身,所以你可以轻松地将它们传递给期望一个可迭代对象的结构中。 - Bergi