Can I make an iterator with a simple function? (No generator or Symbol.iterator)

☆樱花仙子☆ 提交于 2019-12-24 07:25:32

问题


I have been trying to make an iterator using a plain function, without a generator or using the Symbol.iterator protocol for academic purposes. For that, I have made a function that returns an object with a next parameter, but trying to run it as the iterable argument of an for...of loop yields unwanted results.

Here is my code so far, which I copied from the 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};
        }
     };
}

If I try to run it like so:

const iterable = iterateThis([1,2,3,4,5]);
for(item in iterable){
    console.log(item);
}

On the console, I just get a single result: next.

Am I doing something wrong in the creation of the function iterateThis? Or is for...of only designed to work with generators and the Symbol.iterator property?

Executed on Node v8.11.1


回答1:


The problem is that your iterateThis function returns an iterator but the for/of construct expects a iterable.

Okay, wait, whats the difference?

From 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:

On the other hand:

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}

They are related in that calling the @@iterator method of an iterable returns an iterator.

The for/of loop always expects an iterable, so if you want to use for/of, you have to use @@iterator/Symbol.iterator. There's just no way around it as far as I know. But your snippet can be easily modified to use it by just creating an object that returns your iterator when it's Symbol.iterator method is called:

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


来源:https://stackoverflow.com/questions/50917742/can-i-make-an-iterator-with-a-simple-function-no-generator-or-symbol-iterator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!