ES6에서 도입된 순회 가능한 자료구조
ES6 이전
순회 가능한 자료구조 (데이터 컬렉션)들 배열, 문자열, 유사배열, 객체, DOM 컬렉션 등 통일된 규약없이 각자의 구조로 for문, for..in문, forEach 메서드 등 다양한 방법으로 순회
ES6 이후
순회 가능한 자료구조들을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 for..of문, 스프레드 문법, 배열 비구조화 할당의 대상으로 사용할 수 있도록 일원화
이터러블 프로토콜 (Iterable protocol)
Well-known Symbol인 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 상속받은 메서드를 호출하면
이터레이터 프로토콜을 준수한 이터레이터를 반환
이러한 규약을 "이터러블 프로토콜" 이라고 하며 "이터러블 프로토콜을 준수한 객체"를 "이터러블"이라고 함
이터러블은 1. for..of문으로 순회 가능, 2. 스프레드 문법, 3. 배열 비구조화 할당 가능
이터레이터 프로토콜 (Iterator protocol)
이터러블의 Symbol.iterator 메서드를 호출하면
이터레이터 프로토콜을 준수한 이터레이터를 반환
이터레이터는 next메서드를 갖고 있어 이터러블을 순회하며
value와 done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환
이러한 규약을 "이터레이터 프로토콜"이라 "이터레이터 프로토콜을 준수한 객체"를 "이터레이터"라고함
이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할을 함
예시)
크롬 콘솔에 arr = [1, 2, 3]이라는 배열을 생성 후 출력시 다음과 같은 정보가 나옴
아래 Symbol.iterator라는 키를 가진 심볼임을 확인 & Key가 가리키는 값 함수 (f)
즉, 이 함수 (f)가 이터러블 프로토콜을 정의하는 함수
그렇기에 배열은 "이터러블"하다고 말할 수 있음
이터레이터는 next()라는 함수를 호출할 수 있고 value와 done값을 가지는 객체를 리턴함
이렇게 value와 done값을 리턴해주는 next() 함수를 가진 값을 이터레이터 라고 함
따라서,
출처) https://wbluke.tistory.com/34
이터러블을 확인해보는 함수 만들기
*객체는 불가함
하지만 TC39 프로세스의 state4 (Finished) 단계에 제안되어 있는 스프레드 프로퍼티 제안은 일반 객체의 스프레드 문법 사용을 허용
이터레이터의 next 메서드는 이터러블의 각 요소를 순회하기 위한 포인터 역할
즉, next메서드를 호출하면 이터러블을 순차적으로 한 단계씩 순회하여 결과를 나타내는 이터레이터 리절트 객체를 반환함
value 속성 : 현재 순회 중인 값
done 속성 : 순회 완료 여부
for in문
for (변수 in 객체) { ... }
객체의 프로토타입의 프로퍼티 중 프로퍼티 속성 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 "열거"
단, 이때 프로퍼티 키가 심벌인 프로퍼티는 열거 X
for of문
for (변수 of 이터러블) { ... }
for of문은 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 next가 반환한 이터레이터 리절트 객체의 value값을 for..of의 변수에 "할당"
여기서 done값이 false이면 계속 순회하고 true이면 중지
마치 배열처럼 인덱스로 프로퍼티 값에 접근 가능 & length 프로퍼티를 갖는 객체
하지만 유사배열 객체는 이터러블이 아닌 일반 객체기 때문에 for...of으로 순회 불가 (Symbol.iterater 메서드가 없기 때문)
ES6부터 도입된 Array.from 메서드를 활용하면 간단하게 "배열로 변환" 가능
즉,
이터러블을 지원하는 데이터 소비자는 내부에서
Symbol.iterator 메서드를 호출해 이터레이터를 생성하고
이터레이터의 next메서드를 통해 이터러블을 순회하며
이터레이터 리절트 객체를 반환,
그렇기에 쉽게 value, done의 프로퍼티 값을 취득 가능!
이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면 됨
예시)
사용자 정의 이터러블을 활용한 피보나치 수열
*코드 마지막에 for (변수 of 객체)를 통해 next메서드를 활용하여 단계적으로 출력
*이터러블 : [Symbol.iterator]()을 통해 반환 | 이터레이터 : iterator.next()
즉, 이터레이션 프로토콜을 준수하도록
[Symboliterator]()
를 통해 구현하여 next()를 쓸 수 있는 이터레이터를 반환
이렇게 만들어진 피보나치 수열은
스프레드 문법, 배열 비구조화 할당 가능
이렇게 동시에 사용
done값을 생략하여 멈추지 않도록함 (위에서는 지정한 max값 이상시 중지)