JS1.7 SomeClass.prototype.__iterator__ = function() {...}
構文と同じ方法でES6クラスからイテレーターを作成するにはどうすればよいですか?
[編集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]()
にフラグを立て、アスタリスクの直後に「関数名が必要です」という警告を表示しますが、そうでない場合はTraceurでコンパイルおよび実行できます。 (注WebStormは*generator()
に対してエラーを生成しません。)
適切なイテレータメソッドを定義します。例えば:
class C {
constructor() { this.a = [] }
add(x) { this.a.Push(x) }
[Symbol.iterator]() { return this.a.values() }
}
編集:サンプル使用:
let c = new C
c.add(1); c.add(2)
for (let i of c) console.log(i)
クラスインスタンスに対して iterator を返すSomeClass
に対して_Symbol.iterator
_プロパティを指定する必要があります。イテレータには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) }
_
更新された質問で、クラスiteratorからgenerator functionを実現しました。そうすることはできますが、イテレーターはジェネレーターではないことを理解する必要があります。実際、es6のイテレーターは、特定の next()
method を持つオブジェクトです。
ES6で2Dマトリックスのカスタムクラスを反復処理する例を次に示します
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
ドキュメント: 反復プロトコル
iterator protocolとiterable protocolの両方のテクニックを実装するクラスの例:
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;
}
}
オブジェクトを作成するiterableは、このオブジェクトにSymbol.iterator
という名前のメソッドがあることを意味します。このメソッドが呼び出されると、iteratorと呼ばれるインターフェースを返す必要があります。
このイテレータには、次の結果を返すメソッドnext
が必要です。この結果は、次の値を提供するvalue
プロパティと、それ以上結果がない場合はdone
であり、それ以外の場合はtrue
であるfalse
プロパティを持つオブジェクトでなければなりません。 。
また、すべての要素が0
からwidth * height - 1
に及ぶMatrix
というクラスのイテレーターも実装します。このイテレーターにMatrixIterator
と呼ばれる別のクラスを作成します。
class Matrix {
constructor(width, height) {
this.width = width;
this.height = height;
this.content = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
this.content[y * width + x] = y * width + x;
}
}
}
get(x, y) {
return this.content[y * this.width + x];
}
[Symbol.iterator]() {
return new MatrixIterator(this);
}
}
class MatrixIterator {
constructor(matrix) {
this.x = 0;
this.y = 0;
this.matrix = matrix;
}
next() {
if (this.y == this.matrix.height) return {done: true};
let value = {
x: this.x,
y: this.y,
value: this.matrix.get(this.x, this.y)
};
this.x++;
if (this.x == this.matrix.width) {
this.x = 0;
this.y++;
}
return {value, done: false};
}
}
Matrix
は、Symbol.iterator
シンボルを定義することでiteratorプロトコルを実装することに注意してください。このメソッド内で、MatrixIterator
のインスタンスが作成されます。このインスタンスはthis
、つまりMatrix
インスタンスをパラメーターとして受け取り、MatrixIterator
の内部でメソッドnext
は定義済み。 iteratorとSymbol.iterator
の実装が明確に示されているため、このイテレータの実装方法が特に気に入っています。
または、次のようにSymbol.iterator
を直接定義せずに、prototype[Symbol.iterator]
に関数を追加することもできます。
Matrix.prototype[Symbol.iterator] = function() {
return new MatrixIterator(this);
};
let matrix = new Matrix(3, 2);
for (let e of matrix) {
console.log(e);
}