ES6 클래스에서 반복자를 만드는 방법
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)
클래스 인스턴스에 대해 반복기 를 반환 하는 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()
다음은 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
문서 : 반복 프로토콜
반복기 프로토콜 과 반복 가능한 프로토콜 기술을 모두 구현하는 예제 클래스 :
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;
}
}
설명
Making an object iterable means this object has a method named with the Symbol.iterator
. When this method gets called, it should return an interface called iterator.
This iterator must have a method next
that returns the next result. This result should be an object with a value
property that provides the next value, and a done
property, which should be true
when there are no more results and false
otherwise.
Implementation
I will also implement an iterator for a class called Matrix
which all elements will range from 0
to width * height - 1
. I will create a different class for this iterator called 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};
}
}
Notice that Matrix
implements the iterator protocol by defining Symbol.iterator
symbol. Inside this method, an instance of MatrixIterator
is created which takes this
, i.e., the Matrix
instance as parameter, and inside MatrixIterator
, the method next
is defined. I particularly like this way of implementing an iterator because it clearly shows the iterator and the implementation of the Symbol.iterator
.
Alternatively, one can also not define directly Symbol.iterator
, and instead add a function to prototype[Symbol.iterator]
as follows:
Matrix.prototype[Symbol.iterator] = function() {
return new MatrixIterator(this);
};
Usage Example
let matrix = new Matrix(3, 2);
for (let e of matrix) {
console.log(e);
}
ReferenceURL : https://stackoverflow.com/questions/28739745/how-to-make-an-iterator-out-of-an-es6-class
'IT story' 카테고리의 다른 글
__init__.py에서 참조 'xxx'를 찾을 수 없음-Python / Pycharm (0) | 2020.12.30 |
---|---|
spring-boot-starter-web을 사용하여“적용 가능한 표현을 찾을 수 없습니다” (0) | 2020.12.30 |
Google Play 스토어 내부 테스트를 시작할 수 없음 (0) | 2020.12.29 |
C #에서 한 줄씩 파일 읽기 (0) | 2020.12.29 |
Regex : 다른 컨텍스트에서 줄 시작 / 줄 끝 기호 (^ 또는 $) 사용 (0) | 2020.12.29 |