【发布时间】:2016-08-01 07:31:31
【问题描述】:
在 ECMAScript6 中,iterator 是具有 next() 方法的对象,该方法返回具有两个属性的对象:{value, done}。例如:
function createIterator(ra) {
let i = 0;
return {
next() {
if (i < ra.length)
return {value: ra[i++],
done: false};
else
return {value: undefined,
done: true};
}
};
}
创建了一个迭代器后,发现它本身并不是很有用,因为没有内置的语法可以利用迭代器。相反,必须做以下事情:
const it = createIterator(['a', 'b', 'c']);
while (true) {
const o = it.next();
if (o.done)
break;
else
console.log(o.value);
}
另一方面,“Iterable”是一个具有Symbol.iterator 属性的对象,它必须是一个返回迭代器的无参数函数:
function createIterable(ra) {
let it = createIterator(ra);
return {
[Symbol.iterator]() {return it;}
};
}
...当我们创建一个可迭代对象时,我们终于可以使用for of 语法:
for (let v of createIterable(['a', 'b', 'c']))
console.log(v);
看上面的代码,“iterable”对象对“iterator”的附加价值并不容易被察觉。那么为什么Javascript需要iterable和iterator这两个独立的概念呢?顺便说一句,这就是Java does as well,所以一定有一些独立于语言的原因,为什么拥有这两个不同的概念是个好主意。
【问题讨论】:
-
迭代器应该使用
yield,而不是return。迭代器实现惰性求值,如 Python 生成器,没错,Java。 Iterables 只是一种标准化如何迭代对象的方法 - 这来自 C++,其中迭代器旨在标准化对象的迭代,其中不清楚要迭代什么。天壤之别。 -
从概念上讲,“迭代器”包装了迭代操作的当前状态,“可迭代”符号将集合标记为能够提供迭代器。
-
@AkshatMahajan 迭代器和可迭代对象独立存在。生成器(在这方面)只是一种便利。
-
@MarcusJuniusBrutus “当一个对象知道如何一次访问一个集合中的项目时,它就是一个迭代器,同时跟踪它在该序列中的当前位置。” - 来自 Mozilla 文档。 Javascript iterables = Python 中的生成器; JS 生成器是返回迭代器的工厂函数,用词不当——它们与 Python 生成器不对应。迭代器的好处是惰性求值。这就是它存在的原因。
-
@Alnitak 你的评论很有道理。迭代器对象是保存状态的地方,[Symbol.iterator] 方法在每次调用时都会返回一个新的迭代器(具有初始化状态)。