Array is not passed on to next() method while making iterator in JavaScript

I am teaching myself coding, learning Java Script. I am working on a problem from a book where I need to make an iterator for a custom object, which acts like a Set.

When I want to access the array I have set up to hold the data in the next() method, I get the following error:

Uncaught TypeError: Cannot read property ‘length’ of undefined at Object.next (testerBook.js:34) at testerBook.js:83

Within the next() method, it has the array as undefined.

Code is as follows:

class Group {
  constructor() {
    this.values = [];
  }

  add(value) {
    if (!this.values.includes(value)) {
      this.values.push(value);
    }
  }

  delete(value) {
    if (this.values.includes(value)) {
      this.values = this.values.filter(e => e !== value);
    }
  }

  has(value) {
    return this.values.includes(value);
  }

  [Symbol.iterator]() {

    let count = 0;
    let nvalues = this.values;
    console.log('nvalues is ', nvalues);

    return {
      next() {
        console.log('In next in iterator ', this.nvalues);
        //try the ++ count afterwards
        if (count === this.values.length - 1) {
          return {
            value: undefined,
            done: true
          };
        } else {
          count++;
          return {
            value: this.values[count - 1],
            done: false
          };
        }

      }
    }
  }

  static from(newValues) {
    let group = new Group();
    for (let value of newValues) {
      if (!group.has(value)) {
        group.add(value);
      }
    }
    return group;
  }

}


let group = Group.from([1, 2, 3, 4, 3, 2, 1, 5]);
console.log(group.values);
for (let value of group) {
  console.log(value);
}

I’m hoping it is something easy that I dont see. Any help would be appreciated!

Answer

this is not being passed into the next function. You can pass it in implicitly using an arrow function.

Also the iterator ends early, change if (count === this.values.length - 1) { to if (count === this.values.length) {

class Group {
    constructor() {
        this.values = [];
    }

    add(value) {
        if (!this.values.includes(value)) {
            this.values.push(value);
        }
    }

    delete(value) {
        if (this.values.includes(value)) {
            this.values = this.values.filter(e => e !== value);
        }
    }

    has(value) {
        return this.values.includes(value);
    }

    [Symbol.iterator]() {
        
        let count = 0;
        let nvalues = this.values;
        console.log('nvalues is ', nvalues);

        return {
            next: () => {
                console.log('In next in iterator ', JSON.stringify(this,null,2));
                //try the ++ count afterwards
                if (count === this.values.length) {
                    return { value: undefined, done: true };
                } else {
                    count++;
                    return { value: this.values[count - 1], done: false };
                }

            }
        }
    }
    
    static from(newValues) {
      let group = new Group();
      for (let value of newValues) {
        if (!group.has(value)) {
          group.add(value);
        }
      }
      return group;
    }
}

let group = Group.from([1, 2, 3, 4, 3, 2, 1, 5]);
console.log(group.values);
for (let value of group) {
  console.log(value);
}