TypeScript Deep Dive
  • README
  • 시작하기
    • 왜 타입스크립트인가
  • 자바스크립트
    • 비교 연산자
    • 참조 연산자
    • Null vs. Undefined
    • this
    • 클로저
    • Number
    • Truthy
  • 미래의 자바스크립트
    • 클래스
      • 즉시실행함수
    • 화살표 함수
    • 나머지 연산자
    • let
    • const
    • 비구조화 할당
    • 전개 연산자
    • for...of
    • 이터레이터
    • 템플릿 리터럴
    • 프로미스
    • 제네레이터
    • Async Await
  • 프로젝트
    • 컴파일러 제어
      • tsconfig.json
      • 파일 경로 지정
    • 선언
    • 모듈화
      • 파일을 이용한 모듈화
      • globals.d.ts
    • 네임스페이스
    • 동적 표현식 가져오기
  • Node.js 시작하기
  • Browser 시작하기
  • 타입스크립트 타입 시스템
    • 자바스크립트 마이그레이션 가이드
    • @types
    • 주변 선언
      • 파일 선언
      • 변수
    • 인터페이스
    • 열거형(Enums)
    • lib.d.ts
    • 함수
    • 콜러블(Callable)
    • 타입 표명(Type Assertion)
    • 신선도(Freshness)
    • 타입 가드
    • 리터럴(Literal)
    • 읽기 전용(readonly)
    • 제네릭
    • 타입 인터페이스
    • 타입 호환성
    • Never 타입
    • 구별된 유니온
    • 인덱스 서명(Index Signature)
    • 타입 이동하기
    • 예외 처리
    • 믹스인(Mixin)
  • JSX
    • React
    • Non React JSX
  • Options
    • noImplicitAny
    • strictNullChecks
  • 타입스크립트 에러
    • 에러 메세지
    • 공통 에러
  • NPM
  • 테스트
    • Jest
    • Cypress
  • Tools
    • Prettier
    • Husky
    • ESLint
    • Changelog
  • 팁
    • 문자열 Enums
    • 타입 단언
    • 상태 저장 함수
    • 커링
    • 제네릭 타입 예시
    • 객체 타입 설정
    • 유용한 클래스
    • Import / Export
    • 속성 Setters
    • outFile 주의사항
    • 제이쿼리 팁
    • 정적 생성자
    • 싱글톤 패턴
    • 함수 파라미터
    • 토글 생성
    • Import 여러개 하기
    • 배열 생성
    • 생성자에서 타입정의
  • 스타일 가이드
  • 타입스크립트 컴파일러 구조
    • Program
    • AST
      • TIP: Visit Children
      • TIP: SyntaxKind enum
      • Trivia
    • Scanner
    • Parser
      • Parser Functions
    • Binder
      • Binder Functions
      • Binder Declarations
      • Binder Container
      • Binder SymbolTable
      • Binder Error Reporting
    • Checker
      • Checker Diagnostics
      • Checker Error Reporting
    • Emitter
      • Emitter Functions
      • Emitter SourceMaps
    • Contributing
Powered by GitBook
On this page

Was this helpful?

  1. 미래의 자바스크립트

이터레이터

Previousfor...ofNext템플릿 리터럴

Last updated 3 years ago

Was this helpful?

이터레이터 자체는 타입스크립트 혹은 ES6 기능이 아닙니다. 이터레이터는 객체 지향 프로그래밍 언어에서 동작합니다. 그것은 일반적으로 다음 인터페이스를 구현하는 객체입니다.

interface Iterator<T> {
    next(value?: any): IteratorResult<T>
    return?(value?: any): IteratorResult<T>
    throw?(e?: any): IteratorResult<T>
}

() 이 인터페이스를 사용하면 일부 콜렉션 또는 시퀀스에서 값을 검색할 수 있습니다.

그 IteratorResult는 단순히 value+done 쌍입니다.

interface IteratorResult<T> {
    done: boolean
    value: T
}

어떤 프레임의 객체가 있다고 상상해 보십시요, 이 프레임이 구성하는 요소 이터레이터를 사용하면 가능합니다. 아래처럼 프레임 객체에서 컴포넌트를 검색합니다.

class Component {
    constructor(public name: string) {}
}

class Frame implements Iterator<Component> {
    private pointer = 0

    constructor(public name: string, public components: Component[]) {}

    public next(): IteratorResult<Component> {
        if (this.pointer < this.components.length) {
            return {
                done: false,
                value: this.components[this.pointer++]
            }
        } else {
            return {
                done: true,
                value: null
            }
        }
    }
}

let frame = new Frame('Door', [
    new Component('top'),
    new Component('bottom'),
    new Component('left'),
    new Component('right')
])
let iteratorResult1 = frame.next() //{ done: false, value: Component { name: 'top' } }
let iteratorResult2 = frame.next() //{ done: false, value: Component { name: 'bottom' } }
let iteratorResult3 = frame.next() //{ done: false, value: Component { name: 'left' } }
let iteratorResult4 = frame.next() //{ done: false, value: Component { name: 'right' } }
let iteratorResult5 = frame.next() //{ done: true, value: null }

//It is possible to access the value of iterator result via the value property:
let component = iteratorResult1.value //Component { name: 'top' }

그래 좋아, 그러나 많은 도움이 되었어. ES6는 이터러블 프로토콜을 정의합니다 이터러블 인터페이스가 구현 된 경우 [Symbol.iterator] symbol을 포함합니다.

//...
class Frame implements Iterable<Component> {
    constructor(public name: string, public components: Component[]) {}

    [Symbol.iterator]() {
        let pointer = 0
        let components = this.components

        return {
            next(): IteratorResult<Component> {
                if (pointer < components.length) {
                    return {
                        done: false,
                        value: components[pointer++]
                    }
                } else {
                    return {
                        done: true,
                        value: null
                    }
                }
            }
        }
    }
}

let frame = new Frame('Door', [
    new Component('top'),
    new Component('bottom'),
    new Component('left'),
    new Component('right')
])
for (let cmp of frame) {
    console.log(cmp)
}

유감스럽게도 frame.next()는 이 패턴과 함께 작동하지 않을 것으로 보입니다.

//...
class Frame implements IterableIterator<Component> {
    private pointer = 0

    constructor(public name: string, public components: Component[]) {}

    public next(): IteratorResult<Component> {
        if (this.pointer < this.components.length) {
            return {
                done: false,
                value: this.components[this.pointer++]
            }
        } else {
            return {
                done: true,
                value: null
            }
        }
    }

    [Symbol.iterator](): IterableIterator<Component> {
        return this
    }
}
//...

frame.next() 그리고 for 둘다 이터러블이터레이터 인터페이스로 잘 동작합니다.

이터레이터는 이터레이트 값을 가지고 있지 않습니다. 이 예제는 전형적인 피보나치입니다.

class Fib implements IterableIterator<number> {
    protected fn1 = 0
    protected fn2 = 1

    constructor(protected maxValue?: number) {}

    public next(): IteratorResult<number> {
        var current = this.fn1
        this.fn1 = this.fn2
        this.fn2 = current + this.fn1
        if (this.maxValue != null && current >= this.maxValue) {
            return {
                done: true,
                value: null
            }
        }
        return {
            done: false,
            value: current
        }
    }

    [Symbol.iterator](): IterableIterator<number> {
        return this
    }
}

let fib = new Fib()

fib.next() //{ done: false, value: 0 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 2 }
fib.next() //{ done: false, value: 3 }
fib.next() //{ done: false, value: 5 }

let fibMax50 = new Fib(50)
console.log(Array.from(fibMax50)) // [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

let fibMax21 = new Fib(21)
for (let num of fibMax21) {
    console.log(num) //Prints fibonacci sequence 0 to 21
}

Building code with iterators for ES5 target

위의 코드 예제에는 ES6가 필요합니다. 그러나 JS엔진이 Symbol.iterator을 지원한다면 ES5에서도 사용할 수 있습니다. 타겟을 ES5으로 설정하고, ES6 lib를 사용하여 컴파일하면 됩니다 (프로젝트에 es6.d.ts 추가) 컴파일된 코드는 node 4+, Google Chrome 등의 브라우저에서 작동 가능합니다.

다시 말하자면 이터레이터 자체는 타입스크립트 기능이 아닙니다. 이 코드는 이터레이터 및 IteratorResult를 명시적으로 구현합니다. 그리고 이러한 공통점을 사용하는 것은 매우 유용합니다. ES6 for code consistency.

More on that <T> notation later
interfaces