앞서 for 구문을 살펴본 바와 같이 반복기를 이미 경험해 보았다.
반복기의 특징은 다음과 같다.
다음 함수를 만들어서 반복기 제공자(iterable)를 만들어 보자
//number 타입의 from과 to를 받아서
export const createRangeIterable = (from : number, to:num
{
//아래 변수에 from 매개 변수를 넣고
let currentValue = from
return {
//nuxt메서드를 실행하는데
next(){
// value에는 currentValue가 to보다 작으면 1증가, 크면 undefined를 반환한다.
const value = currentValue < to ? currentValue ++ : undefined
// 만약 value가 undefined가 되면 done이라는 변수에 넣어서
const done = value == undefined
// value와 done을 리턴한다.
return {value, done}
}
}
}
다음과 같이 사용할 수 있다.
import {createRangeIterable} from './export';
//1~3까지 출력하고 싶어서 3을 명시하기 위한 두번째 매개변수의 3 + 1표현
// 아직 next메서드가 실행되지 않기 때문에 동작하지 않는다.
const iterator = createRangeIterable(1,3+1)
while(true){
// 리턴값을 객체분해할당을 하여 메소드를 실행하도록 한다.
const {value, done} = iterator.next();
// 만약 done이 참이라면 break하여 while문을 나간다.
if(done) break
// 아니라면 value를 띄운다.
console.log(value)
}
위의 코드에서 iterator.next 메서드가 반복 호출 될 때마다 각기 다른 값이 출력이 된다. 반복기 제공자가 생성한 값 1,2,3을 배열에 담아서 출력하지 않고 for 문을 돌면서 콘솔 출력문으로 찍어 내듯한 모습이다.
반복기 제공자는 이처럼 어떤 범위의 값을 한번에 생성해서 배열에 담지 않고 값이 필요 할 때만 생성한다. (next 메소드)
함수로 만들어서 iterator를 for of 문에 사용하면 Symbol객체가 없다는 에러가 발생한다. for of 문을 사용하고 싶으면 [Symbol.iterator]메서드를 구현해야 한다.
클래스로 만들어서 해당 메서드를 구현 할 수 있다.
export class RangeIterable{
constructor(public from:number, public to:number){
}
[Symbol.iterator](){
const that = this
let currentValue = that.from
return {
next(){
const value = currentValue < that.to ? currentValue++ : undefined
const done = value == undefined
return {value, done}
}
}
}
}
위와 같이 Symbol.iterator메서드를 클래스로 구현하고 아래에 사용하면 잘 되는 것을 확인 할 수 있다.
import {RangeIterable} from './range'
const iterator = new RangeIterable(1, 3 + 1)
for(let value of iterator)
console.log(value)
타입스크립트는 반복자 제공자에 제네릭 인터페이스를 사용할 수 있다.
Iterable는 자신을 구현하는 클래스가 [Symbol.iterator]메서드를 제공한다는 것을 명확하게 알려주는 역할을 한다.
class 구현클래스 implements Iterable<생성할 값의 타입>{ }
또한 제네릭 인터페이스는 반복기가 생성할 값의 타입을 명확하게 해준다.
[Symbol.iterator]( ) : Iterator<생성할 값의 타입> { }
export class StringIterable implements Iterable<string>{
constructor(private strings:string[] = [], private currentIndex:number = 0){
}
[Symbol.iterator]():Iterator<string>{
const that = this
let currentIndex = that.currentIndex, length = that.strings.length
const iterator:Iterator<string> = {
next():{value : string, done : boolean}{
const value = currentIndex < length ? that.strings[currentIndex++] : undefined
const done = value == undefined
return {value, done}
}
}
return iterator
}
}
위 코드를 실행하면 StringIterable 클래스의 strings 속성에 담긴 배열의 아이템을 하나씩 출력한다.
import {StringIterable} from './stringIterable'
for(let value of new StringIterable(['helloe', 'world', '!']))
console.log(value)