-
JavaScript - iterable 객체Frontend/JavaScript 2021. 7. 7. 20:26
- iterable 객체
- 반복 가능한(iterable) 객체
- for ...of 반복문 적용 가능
- 이터러블 객체 종류
- 배열, 다수의 내장 객체, 문자열 등
- 배열, 다수의 내장 객체, 문자열 등
- Symbol.iterator
- 배열이 아닌 객체를 이터러블 객체로 변경
- 아래 range 객체를 이터러블로 만드려면 객체에 Symbol.iterator(특수 내장 심볼) 메소드 추가
1. for ...of 가 시작되자마자 for ...of 는 Symbo.iterator 호출(Symbol.iterator 없으면 에러 발생)
Symbol.iterator는 반드시 이터레이터(iterator, 메소드 next가 있는 객체) 를 반환해야 함
2. 이후 for ...of 는 반환된 객체(이터레이터)만을 대상으로 동작
3. for ...of 에 다음 값이 필요하면, for ...of 는 이터레이터의 next() 메소드 호출
4. next()의 반환 값은 { done: Boolean, value: any } 와 같은 형태- done=true 는 반복이 종료되었음을 의미
- done=false 일때는 value에 다음 값이 저장됨
let range = { from: 1, to: 5 }; // 1. for..of 최초 호출 시, Symbol.iterator가 호출됩니다. range[Symbol.iterator] = function() { // Symbol.iterator는 이터레이터 객체를 반환합니다. // 2. 이후 for..of는 반환된 이터레이터 객체만을 대상으로 동작하는데, 이때 다음 값도 정해집니다. return { current: this.from, last: this.to, // 3. for..of 반복문에 의해 반복마다 next()가 호출됩니다. next() { // 4. next()는 값을 객체 {done:.., value :...}형태로 반환해야 합니다. if (this.current <= this.last) { return { done: false, value: this.current++ }; } else { return { done: true }; } } }; }; // 이제 의도한 대로 동작합니다! for (let num of range) { alert(num); // 1, then 2, 3, 4, 5 }
- 이터러블 객체의 핵심은 '관심사의 분리(Separation of concern, SoC)'
- range에는 next() 메소드가 없다.
- 대신 range[Symbol.iterator]()를 호출해서 만든 '이터레이터' 객체와 이 객체의 메소드 next()에서 반복에 사용될 값을 만들어낸다.
- 이렇게 하면 이터레이터 객체와 반복 대상인 객체를 분리할 수 있다.
- 이터레이터 객체와 반복 대상 객체를 합쳐서 range 자체를 이터레이터로 만들면 코드가 더 간단해진다.
let range = { from: 1, to: 5, [Symbol.iterator]() { this.current = this.from; return this; }, next() { if (this.current <= this.to) { return { done: false, value: this.current++ }; } else { return { done: true }; } } }; for (let num of range) { alert(num); // 1, then 2, 3, 4, 5 }
- range[Symbol.iterator]() 가 객체 range 자체를 반환
- 반한된 객체에는 필수 메소드인 next()가 존재하고 this.current 에 반복이 얼마나 진행되었는지를 나타내는 값도 저장되어 있다.
- 단점
- 두개의 for ...of 반복문을 하나의 객체에 동시에 사용할 수 없다는 점
( 이터레이터(객체 자신)가 하나뿐이여서 두 반복문이 반복 상태를 공유하기 때문 )
- 두개의 for ...of 반복문을 하나의 객체에 동시에 사용할 수 없다는 점
- 반한된 객체에는 필수 메소드인 next()가 존재하고 this.current 에 반복이 얼마나 진행되었는지를 나타내는 값도 저장되어 있다.
- 이터레이터를 명시적으로 호출하기
let str = "Hello"; // for..of를 사용한 것과 동일한 작업을 합니다. // for (let char of str) alert(char); let iterator = str[Symbol.iterator](); while (true) { let result = iterator.next(); if (result.done) break; alert(result.value); // 글자가 하나씩 출력됩니다. }
- 요약
- for ...of 를 사용할 수 있는 객체를 이터러블(iterable)이라고 한다.
- 이터러블에는 메소드 Symbol.iterator 가 반드시 구현되어 있어야 한다.
- obj[Symbol.iterator] 의 결과는 이터레이터 라고 부른다. 이터레이터는 이어지는 반복 과정을 처리한다.
- 이터레이터엔 객체 { done: Boolean, value: any } 를 반환하는 메소드 next() 가 반드시 구현되어 있어야 한다.
- 메소드 Symbol.iterator 는 for ...of 에 의해 자동으로 호출되는데, 개발자가 명시적으로 호출하는 것도 가능하다.
- 문자열이나 배열 같은 내장 이터러블에도 Symbol.iterator 가 구현되어 있따.
[ 참고자료 ]
https://ko.javascript.info/iterable
'Frontend > JavaScript' 카테고리의 다른 글
JavaScript - Map, Set (0) 2021.07.08 JavaScript - iterable, 유사 배열, Array.from (0) 2021.07.07 JavaScript - for ...of, for ...in 차이 (0) 2021.07.07 JavaScript - isNaN() vs Number.isNaN() (0) 2021.07.07 JavaScript - new 연산자와 생성자 함수 (0) 2021.07.06