Generator can run with for .. of and ..., which will only emit yield values 

For example:

function* count() {
    yield 1;
    yield 2;
    return 3;
}

for (const value of count()) {
   console.log(value) // 1, 2
}


console.log([...count()]) // [1, 2]

 

Iterator

Using [Symbol.iterator]()which should return next() function:

const range = {
    from: 1,
    to: 5,
    [Symbol.iterator]() {
        return {
             current: this.from,
             last: this.to,
             next() {
                 if (this.current <= this.last) {
                     return {done: false, value: this.current++}
                 } else {
                     return {done: true}
                 }
             }
        }
    }
}

console.log([...range]) // [1,2,3,4,5]

 

Or we can also just do geneator appraoch:

const range = {
    from: 1,
    to: 5,
    *[Symbol.iterator]() {
        for (let i = this.from; i <= this.to; i++) {
           yield i
        }
    }
}

console.log([...range]) // [1,2,3,4,5]

 

One usecase for geneator and iterator is that not overload the data, everytime can just load a small tunck of data to process with next() call instead of loading the whole data into memory