Как сделать итератор из класса ES6

как бы я сделал итератор из класса ES6 таким же образом, как JS1.7 SomeClass.prototype.__iterator__ = function() {...} синтаксис?

[EDIT 16: 00]

следующие работы:

class SomeClass {
    constructor() {
    }

    *[Symbol.iterator]() {
        yield '1';
        yield '2';
    }

    //*generator() {
    //}

}

an_instance = new SomeClass();
for (let v of an_instance) {
    console.log(v);
}

флаги WebStorm *[Symbol.iterator]() с предупреждением "имя функции ожидается" непосредственно после asterix, но в противном случае это компилируется и отлично работает с Traceur. (Примечание. WebStorm не создает ошибок для *generator().)

5 ответов


определите подходящий метод итератора. Например:

class C {
  constructor() { this.a = [] }
  add(x) { this.a.push(x) }
  [Symbol.iterator]() { return this.a.values() }
}

Edit: пример использования:

let c = new C
c.add(1); c.add(2)
for (let i of c) console.log(i)

необходимо указать Symbol.iterator собственность за SomeClass возвращает итератор для экземпляров класса. Итератор должен иметь next() метод, ведьма, в свою очередь, возвращает объект с done и value поля. Упрощенный пример:

function SomeClass() {
  this._data = [1,2,3,4];
}

SomeClass.prototype[Symbol.iterator] = function() {
  var index = 0;
  var data  = this._data;

  return {
    next: function() {
      return { value: data[++index], done: !(index in data) }
    }
  };
};

или с помощью классов ES6 и функций со стрелками:

class SomeClass {
  constructor() {
    this._data = [1,2,3,4];
  }

  [Symbol.iterator]() {
    var index = -1;
    var data  = this._data;

    return {
      next: () => ({ value: data[++index], done: !(index in data) })
    };
  };
}

и использование:

var obj = new SomeClass();
for (var i of obj) { console.log(i) }

в вашем обновленном вопросе вы поняли класс итератор через функции генератора. Вы можете это сделать, но вы должны понимать, что итератор не может быть генератором. На самом деле итератор в es6-это любой объект, который имеет определенный next() метод


вот пример итерации по 2D-матричному пользовательскому классу в ES6

class Matrix {
    constructor() {
        this.matrix = [[1, 2, 9],
                       [5, 3, 8],
                       [4, 6, 7]];
    }

    *[Symbol.iterator]() {
        for (let row of this.matrix) {
            for (let cell of row) {
                yield cell;
            }
        }
    }
}

использование такого класса было бы

let matrix = new Matrix();

for (let cell of matrix) {
    console.log(cell)
}

что бы выход

1
2
9
5
3
8
4
6
7

документы: Протоколы Итерации

пример класса, реализующего как итератор протокол и iterable протокол методы:

class MyCollection {
  constructor(elements) {
    if (!Array.isArray(elements))
      throw new Error('Parameter to constructor must be array');

    this.elements = elements;
  }

  // Implement "iterator protocol"
  *iterator() {
    for (let key in this.elements) {
      var value = this.elements[key];
      yield value;
    }
  }

  // Implement "iterable protocol"
  [Symbol.iterator]() {
    return this.iterator();
  }
}

элементы доступа с использованием любой техники:

var myCollection = new MyCollection(['foo', 'bar', 'bah', 'bat']);

// Access elements of the collection using iterable
for (let element of myCollection)
  console.log('element via "iterable": ' + element);

// Access elements of the collection using iterator
var iterator = myCollection.iterator();
while (element = iterator.next().value)
  console.log('element via "iterator": ' + element);

пример класса итератора ES6, который хранится в подобъекте:

class Iterator {
    data;

    constructor(data = {}) {
        this.data = JSON.parse(JSON.stringify(data));
    }

    add(key, value) { this.data[key] = value; }

    get(key) { return this.data[key]; }

    [Symbol.iterator]() {
        const keys = Object.keys(this.data).filter(key => 
        this.data.hasOwnProperty(key));
        const values = keys.map(key => this.data[key]).values();
        return values;
    }
}