Search code examples
javascriptiterable

How can I make an iterable in JavaScript?


I'm trying to understand iterables in JavaScript by creating a range function, but it doesn't work

I'm trying to understand iterables in JavaScript so I created a range function that when I call it, it will return a range of numbers for me e.g:

for (let i of Range(5)) console.log(i);
0
1
2
3
4

here is the code for doing it.

// log function
const log = console.log;

// Range constructor 
function Range(end, start, step = 1) {
    if (!new.target) {
        return new Range(start, end, step);
    }
    end = start ? start : end;
    start = start ? end : 0;
    step = step;
    
    return {
        start,
        end,
        step,
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (this.start < this.end) {
                this.start += this.step;
                return {
                    done: false,
                    value: this.start - this.step
                };
            } else {
                return { done: true };
            }
        }
    }
}

but when I run it, return the numbers one after another e.g.

let range = new Range(6);
for (i of range) log(i);

Output

0
1
2
3
4
5

but when I run it like for (let i of Range(5) log(i); it return undefined Why!

update if fixed the problem by updating return new Range(start, end, step); to return new Range(end, start, step); and end = start ? start : end; to end = start ?? end;

so when I run

let range = new Range(5); 
for (let i of range) log( i ); // 0, 1, 2, 3, 4
for (let i of Range(10) ) log( i ); // 0, 1, 2, 3, 4

but a new problem raised

let arr = Array.from(range); 
log(arr) // []

how to fix it


Solution

  • You have mixed up your arguments in new Range(start, end, step) (thanks @Unmitigated). It should be new Range(end, start, step).


    FYI a generator function is far simpler.

    function* range(start, end, step = 1) {
      if (end === undefined) {
        end = start;
        start = 0;
      }
      for (; start < end; start += step) {
        yield start;
      }
    }