Search code examples
javascriptclassobjectarrow-functionsiterable

Problem making an object iterable using an arrow function


I am learning JavaScript, I created a class and now I need to make it iterable.
The class Group is a Set of values with methods to add, remove and check the elements of the set.

The part of creating the class was a previous exercise of my textbook, I saw the solution for that part and I tested it, it is correct for sure. My problem is from[Symbol.iterator] on.
Here is the code

class Group {

    constructor() {

        this.theGroup = [];
    }

    add( element ) {

        if( !this.has(element) ) this.theGroup.push(element);
    }

    remove( element ) {

        this.theGroup = this.theGroup.filter( x => x != element );
    }

    has( element ) {

        return this.theGroup.includes(element);
    }

    static from( elements ) {

        let group = new Group;

        for( const x of elements ) {

            group.add(x);
        }

        return group;
    }

    [Symbol.iterator]() {

        let i = 0;

        return next = () => {

            if( i >= this.theGroup.length ) return { done : true };

            else return { value : this.theGroup[i++], done : false };
        };
    }
    
}

// the following is here only to show that the code before [Symbol.iterator] works

const group = Group.from([10, 20]);

console.log(group.has(10));
group.add(10);
group.remove(10);
console.log(group.has(10));
group.remove(10);
console.log(group.has(20));

// end of demostration

for (let value of Group.from(["a", "b", "c"])) {
  console.log(value);
}

I get the error

return next = () => {
       ^
ReferenceError: next is not defined

And if I make the arrow function anonymous: return () => { ...code continues then I got this other error

for (let value of Group.from(["a", "b", "c"])) {
         ^
TypeError: undefined is not a function

I am using an arrow function to avoid changing this.

Someone knows what's going on?
How can I make the class iterable?


Solution

  • You want to return an object with a key of next,.

    eg.. { next: () => {}} not return next = () => {}

    Fixed example below..

    class Group {
    
        constructor() {
    
            this.theGroup = [];
        }
    
        add( element ) {
    
            if( !this.has(element) ) this.theGroup.push(element);
        }
    
        remove( element ) {
    
            this.theGroup = this.theGroup.filter( x => x != element );
        }
    
        has( element ) {
    
            return this.theGroup.includes(element);
        }
    
        static from( elements ) {
    
            let group = new Group;
    
            for( const x of elements ) {
    
                group.add(x);
            }
    
            return group;
        }
    
        [Symbol.iterator]() {
    
            let i = 0;
    
            return {next: () => {
    
                if( i >= this.theGroup.length ) return { done : true };
    
                else return { value : this.theGroup[i++], done : false };
            }};
        }
        
    }
    
    // the following is here only to show that the code before [Symbol.iterator] works
    
    const group = Group.from([10, 20]);
    
    console.log(group.has(10));
    group.add(10);
    group.remove(10);
    console.log(group.has(10));
    group.remove(10);
    console.log(group.has(20));
    
    // end of demostration
    
    for (let value of Group.from(["a", "b", "c"])) {
      console.log(value);
    }