我可以使用简单的函数创建一个迭代器吗? (没有生成器或Symbol.iterator)

时间:2018-06-18 21:30:42

标签: javascript iterator iterable

我一直在尝试使用普通函数创建一个迭代器,没有生成器或使用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上执行

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);
}