我可以用一个简单的函数制作一个迭代器吗? (没有生成器或 Symbol.iterator)
Can I make an iterator with a simple function? (No generator or Symbol.iterator)
我一直在尝试使用普通函数制作迭代器,不使用生成器或出于学术目的使用 Symbol.iterator
协议。为此,我创建了一个函数 returns 一个带有 next
参数的对象,但试图 运行 它作为 for...of
循环的 iterable
参数产生不需要的结果。
到目前为止,这是我的代码,是我从 Iterators and Generators page on MDN:
复制的
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
属性?
在节点 v8.11.1 上执行
问题是您的 iterateThis
函数 returns 是一个 迭代器 但 for/of
构造需要一个 iterable.
好的,等等,有什么区别?
来自 MDN's page on iteration protocols:
In order to be iterable, an object must implement the @@iterator
method, meaning that the object (or one of the objects up its
prototype chain) must have a property with a @@iterator
key which is
available via constant Symbol.iterator
:
另一方面:
An object is an iterator when it implements a next()
method with the
following semantics: Ommited due to length, TL;DR: The next method
returns an object of the form: {value: T, done: boolean}
它们的相关性在于调用 iterable returns 和 iterator 的 @@iterator
方法。
for/of
循环总是需要一个可迭代的,所以如果你想使用 for/of
,你必须使用 @@iterator
/Symbol.iterator
。据我所知,没有办法解决它。但是你的代码片段可以很容易地修改为使用它,只需创建一个对象,当它的 Symbol.iterator
方法被调用时 returns 你的迭代器:
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);
}
我一直在尝试使用普通函数制作迭代器,不使用生成器或出于学术目的使用 Symbol.iterator
协议。为此,我创建了一个函数 returns 一个带有 next
参数的对象,但试图 运行 它作为 for...of
循环的 iterable
参数产生不需要的结果。
到目前为止,这是我的代码,是我从 Iterators and Generators page on MDN:
复制的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
属性?
在节点 v8.11.1 上执行
问题是您的 iterateThis
函数 returns 是一个 迭代器 但 for/of
构造需要一个 iterable.
好的,等等,有什么区别?
来自 MDN's page on iteration protocols:
In order to be iterable, an object must implement the
@@iterator
method, meaning that the object (or one of the objects up its prototype chain) must have a property with a@@iterator
key which is available via constantSymbol.iterator
:
另一方面:
An object is an iterator when it implements a
next()
method with the following semantics: Ommited due to length, TL;DR: The next method returns an object of the form:{value: T, done: boolean}
它们的相关性在于调用 iterable returns 和 iterator 的 @@iterator
方法。
for/of
循环总是需要一个可迭代的,所以如果你想使用 for/of
,你必须使用 @@iterator
/Symbol.iterator
。据我所知,没有办法解决它。但是你的代码片段可以很容易地修改为使用它,只需创建一个对象,当它的 Symbol.iterator
方法被调用时 returns 你的迭代器:
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);
}