본문 바로가기

Javascript/Javascript(ES6)

이터레이터(Iterator)와 for of 문(인덱스말고 값을 순회한다.)

이터레이터(Iterator)

이터레이터는 '반복자'라는 의미로, 이터러블(Iterable, 순회 가능한 자료구조)의 요소를 탐색하기 위한 포인터로서 next()함수를 가지고 있는 객체다.

단순하게 '컬렉션을 반복할 수 있게 하는 객체' 정도로 이해해본다.

지난 포스트에서도 알아봤듯이 Array, String, Map, Set, DOM이 이터러블이고, 이런 것을 반복할 수 있게 하는 것이 이터레이터다.

ex) Array.prototype[Symbol.iterator] ,String.prototype[Symbol.iterator], ...

1
2
3
4
5
6
7
8
const iterable = ['a''b''c'];
const iterator = iterable[Symbol.iterator]();
 
// 이터레이터는 value, done 프로퍼티를 갖는 next()메소드 함수로 이터러블 순회가 가능하다.
console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }


사용법도 간단하다. iterable 객체를 생성하고, 이터레이터를 받아와서, next()로 순회.

마찬가지로 value, done 프로퍼티 접근은 iterator.next().value / iterator.next().done

for~of 문

for~of문은 이터러블 객체를 순회할 때 사용할 수 있다.

for~of문은 next()로 전체를 순회한다. (done값이 true가 될 때까지)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 배열
for (const val of ['a''b''c']) {
  console.log(val);// "a","b","c"
}
// 문자열
for (const val of 'abc') {
  console.log(val);//"a","b","c"
}
// Map
for (const [key, value] of new Map([['a''1'], ['b''2'], ['c''3']])) {
  console.log(`key : ${key} value : ${value}`); // "key : a value : 1", "key : b value : 2", ...
}
// Set
for (const val of new Set([123])) {
  console.log(val);// 1, 2, 3
}
cs

for~in문이랑은 무엇이 차이가 날까?

=> for~of문은 값을 리턴한다.

for~in에서는 인덱스가 리턴되었지만 for~of는 값이 리턴되어 바로 값을 사용할 수 있다. (위에서는 val)

배열의 foreach쓰면 되는거 아닌가? -> foreach는 중간에 break, return을 할 수 없다.

1
2
for (var i in 'string') { alert(i); } // 0, 1, 2, 3, 4, 5
for (var i of 'string') { alert(i); } // s, t, r, i, n, g
cs

커스텀 이터러블(Custom iterable)

임의로 만든 객체는 이터러블이 아니다. 따라서 이터러블 객체를 만들어서 순회를 할 수 있어야 한다.

이터레이션 프로토콜이라고 해서 두 가지 조건을 만족하면 된다.

1. 어떤 객체는 [Symbol.iterator]를 구현하고 있고, iterator를 리턴해야 한다.

2. 그 iterator 객체는 next()를 구현하고 있고, value, done 프로퍼티를 갖는 객체를 반환해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var countdown = {
    max: 3,
    [Symbol.iterator]() {
        // Its ok to return 'this' because it implements the next function.
        return this;
    },
    next() {
        if (this._max === undefined) {
            this._max = this.max;
        }
        if (this._max > -1) {
            return {value: this._max--}; // As long as you have a value
        } else {
            return {done: true}; // When you are out of values
        }
    }
};
var v = countdown[Symbol.iterator]();
console.log(v.next());//value : 3
console.log(v.next());//value : 2
console.log(v.next());//value : 1
console.log(v.next());//value : 0
console.log(v.next());//done : true



참고사이트

https://blog.perfectacle.com/2017/04/22/es6-iterator/

https://www.zerocho.com/category/EcmaScript/post/575d4ea816eb22d05a7dc675

http://javascript.tutorialhorizon.com/2015/07/23/es6-iterators-part-2-creating-custom-iterators/