2015-02-26 4 views
38

Wie würde ich einen Iterator aus einer ES6-Klasse in der gleichen Weise wie JS1.7 SomeClass.prototype.__iterator__ = function() {...} Syntax machen?Wie mache ich einen Iterator aus einer ES6-Klasse

[EDIT 16.00]

Die folgenden Werke:

class SomeClass { 
    constructor() { 
    } 

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

    //*generator() { 
    //} 

} 

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

WebStorm Flaggen *[Symbol.iterator]() mit einem 'Funktionsnamen erwartet' direkt die asterix folgende Warnung, aber ansonsten das kompiliert und läuft gut mit Traceur . (Hinweis WebStorm erzeugen keine Fehler für *generator().)

+0

Dieser Code funktioniert gut für mich im Knoten 'v8.1.1' –

Antwort

19

hat Definieren Sie eine geeignete Iterator-Methode. Zum Beispiel:

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

Edit: Beispiel Verwendung:

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

Und Präfix mit einem Asterix als Generatorfunktion nach dem Aussehen zu verwenden. – user5321531

+8

Dieses spezielle Beispiel verwendet keinen Generator. Es wird einfach an einen Array-Iterator delegiert. –

+0

Könnten Sie bitte ein Beispiel für diesen Code hinzufügen? Ich kann es nicht zur Arbeit bringen. – timkay

18

Sie müssen Symbol.iterator Eigenschaft, um für SomeClass, die für Klasseninstanzen iterator zurückgibt. Iterator muss next() Methode haben, die wiederum Objekt mit done und value Felder zurückgibt. Vereinfachtes Beispiel:

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) } 
    } 
    }; 
}; 

Oder mit ES6 Klassen und Pfeil Funktionen:

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) }) 
    }; 
    }; 
} 

Und Nutzung:

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

In Ihrer aktualisierten Frage realisiert man Klasse Iterator durch Generatorfunktion . Sie können dies tun, aber Sie müssen verstehen, dass Iterator KEIN Generator sein könnte. Tatsächlich Iterator in es6 ist jedes Objekt, das spezifische next() method

+0

Siehe bearbeiten zur ursprünglichen Frage. – user5321531

+0

Das funktioniert tatsächlich, besser als die Antwort als richtig markiert. Vielen Dank! –

9

Hier ist ein Beispiel für

in ES6 über eine 2D-Matrix benutzerdefinierte Klasse Iterieren
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; 
      } 
     } 
    } 
} 

Die Verwendung einer solchen Klasse sein würde

let matrix = new Matrix(); 

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

Welche wou ld Ausgang

1 
2 
9 
5 
3 
8 
4 
6 
7 
+0

Hinweis: Der obige Code benötigt möglicherweise die neueste Version von nodeJS. Es kompiliert fein unter Verwendung von 'node v8.1.1' –

+2

Sie können den Iterator vereinfachen, indem Sie' for ... of' Schleifen verwenden: 'for (let row of this.matrix) {for (let Zelle der Zeile) {yield cell; }} ' –

+1

@LukeMWillis - Nett! Viel besser. Aktualisierte Antwort –

6

Dokumentation: Iteration Protocols

Beispiel Klasse sowohl Iterator-Protokoll und iterable Protokoll Techniken Umsetzung:

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(); 
    } 
} 

Access-Elemente unter Verwendung von entweder Technik:

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);