2015-02-26 16 views
38

Come dovrei fare un iteratore fuori di una classe ES6 nello stesso modo come JS1.7 SomeClass.prototype.__iterator__ = function() {...} sintassi?Come fare un iteratore fuori di una classe ES6

[EDIT 16:00]

le seguenti opere:

class SomeClass { 
    constructor() { 
    } 

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

    //*generator() { 
    //} 

} 

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

bandiere WebStorm *[Symbol.iterator]() con un 'nome di funzione prevista' avvertimento subito dopo l'asterisco, ma altrimenti questo si compila e funziona bene con Traceur . (Nota WebStorm non genera errori per *generator().)

+0

Questo codice funziona bene per me in nodo 'v8.1.1' –

risposta

19

definire un metodo iteratore adatto. Per esempio:

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

Edit: l'uso del campione:

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

E prefisso con un asterisco da utilizzare come funzione generatore dagli sguardi. – user5321531

+8

Questo particolare esempio non utilizza un generatore. Si tratta semplicemente della delega a un iteratore di array. –

+0

Potrebbe essere utile aggiungere un esempio di questo codice? Non riesco a farlo funzionare. – timkay

18

È necessario specificare Symbol.iterator immobili per SomeClass che restituisce iterator per istanze di classe. Iteratore deve avere next() metodo, strega dei rendimenti sua volta oggetto con done e value campi. esempio semplificato:

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

o utilizzando classi ES6 e funzioni di direzione:

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

e di utilizzo:

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

nella tua domanda aggiornato si rese conto di classe iteratore attraverso funzione di generatore di . Puoi farlo, ma devi capire che l'iteratore NON POTREBBE ESSERE un generatore. Effettivamente iterazione in ES6 è qualsiasi oggetto che ha determinato next() method

+0

Vedi modifica alla domanda iniziale. – user5321531

+0

In realtà funziona, meglio della risposta contrassegnata come corretta. Grazie! –

9

Ecco un esempio per iterare su una classe personalizzata matrice 2D in 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; 
      } 
     } 
    } 
} 

L'utilizzo di tale classe sarebbe

let matrix = new Matrix(); 

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

Quale wou uscita ld

1 
2 
9 
5 
3 
8 
4 
6 
7 
+0

Nota: il codice sopra riportato potrebbe richiedere l'utilizzo dell'ultima versione di nodeJS. Compila bene usando 'node v8.1.1' –

+2

Puoi semplificare l'iteratore usando i cicli' for ... of': 'for (let row of this.matrix) {for (let cell of row) {yield cell; }} ' –

+1

@LukeMWillis - Bello! Molto meglio. Risposta aggiornata –

6

Documentation: Iteration Protocols

classe Esempio applicazione sia il protocollo iteratore e iterabili protocollo tecniche:

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

elementi di accesso utilizzando due tecniche:

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