1

I'm currently working on a Eloquent JavaScript's object assignments and I'm wondering if there is any way that I can use this inside iterator's next() method (see the code)

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

  add(member) {
    if (this.has(member)) return;
    this.members.push(member);
  }

  delete(member) {
    if (!this.has(member)) return;
    this.members.splice(this.members.indexOf(member), 1);
  }

  has(member) {
    return this.members.indexOf(member) !== -1
  }

  static from(iterable) {
    const group = new Group();
    for (const element of iterable) {
      group.add(element);
    }

    return group;
  }

  [Symbol.iterator]() {
    let current = 0;
    let last = this.members.length - 1;

    const that = this;

    return {
      next() {
        if (current <= last) {
          return {
            done: false,
            value: that.members[current++]
          }
        } else return { done:true }
      }
    }
  }
}

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

As you can see there I'm using this weird const that = this pattern. Is there any way I can get rid of it? Besides using arrow function and extracting iterator to a separate class, as suggested in the solution.

Oscar
  • 805
  • 2
  • 10
  • 24

2 Answers2

2

The sortest way, could be an implementation of a default iterator of the object in the constructor section and use yield* expression for delegating to another generator of the array this.members.

constructor() {
    this.members = [];
    this[Symbol.iterator] = function* () {
        yield* this.members;
    }
}

class Group {
    constructor() {
        this.members = [];
        this[Symbol.iterator] = function* () {
            yield* this.members;
        }
    }

    add(member) {
        if (this.has(member)) return;
        this.members.push(member);
    }

    delete(member) {
        if (!this.has(member)) return;
        this.members.splice(this.members.indexOf(member), 1);
    }

    has(member) {
        return this.members.indexOf(member) !== -1
    }

    static from(iterable) {
        const group = new Group();
        for (const element of iterable) {
            group.add(element);
        }
        return group;
    }
}

for (let value of Group.from(["a", "b", "c"])) {
    console.log(value);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

you can use the arrow function

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

  add(member) {
    if (this.has(member)) return;
    this.members.push(member);
  }

  delete(member) {
    if (!this.has(member)) return;
    this.members.splice(this.members.indexOf(member), 1);
  }

  has(member) {
    return this.members.indexOf(member) !== -1
  }

  static from(iterable) {
    const group = new Group();
    for (const element of iterable) {
      group.add(element);
    }

    return group;
  }

  [Symbol.iterator]() {
    let current = 0;
    let last = this.members.length - 1;
    return {
      next: () => {
        if (current <= last) {
          return {
            done: false,
            value: this.members[current++]
          }
        } else return { done:true }
      }
    }
  }
}

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