我一直在尝试使用普通函数创建一个迭代器,没有生成器或使用Symbol.iterator
协议用于学术目的。为此,我创建了一个返回带有next
参数的对象的函数,但是尝试将其作为iterable
循环的for...of
参数运行会产生不需要的结果。
到目前为止,这是我的代码,我是从http://selenium-python.readthedocs.io/waits.html复制的:
function iterateThis(arr){
let i = 0;
return {
next: function() {
return i < arr.length ?
{value: arr[i++], done: false} :
{done: true};
}
};
}
如果我尝试像这样运行它:
const iterable = iterateThis([1,2,3,4,5]);
for(item in iterable){
console.log(item);
}
在控制台上,我得到一个结果:next
。
我是否在创建函数iterateThis
时做错了什么?或for...of
仅设计用于生成器和Symbol.iterator
属性?
在Node v8.11.1上执行
答案 0 :(得分:4)
问题是你的iterateThis
函数返回迭代器,但for/of
构造需要 iterable 。
好的,等等,差异是什么?
来自MDN's page on iteration protocols:
为了可迭代,对象必须实现
获得@@iterator
方法,意思是对象(或其中一个对象) 原型链)必须具有@@iterator
键的属性 可以通过常量Symbol.iterator
:
另一方面:
对象是一个迭代器,它实现了
next()
方法 以下语义:由于长度而受限制,TL; DR:下一个方法 返回以下格式的对象:{value: T, done: boolean}
它们的相关之处在于调用 iterable 的@@iterator
方法会返回迭代器。
for/of
循环始终需要可迭代,因此如果您要使用for/of
,则必须使用@@iterator
/ Symbol.iterator
。据我所知,它没有办法绕过它。但是,只需创建一个在调用Symbol.iterator
方法时返回迭代器的对象,就可以轻松修改您的代码段以使用它:
function iterateThis(arr){
let i = 0;
return {
next: function() {
return i < arr.length ?
{value: arr[i++], done: false} :
{done: true};
}
};
}
function makeIterableFromIterator(iterator) {
return {
[Symbol.iterator]: function() {
return iterator;
}
}
}
const iterator = iterateThis([1, 2, 3, 4, 5]);
const iterable = makeIterableFromIterator(iterator);
for (item of iterable) {
console.log(item);
}