이터레이션 프로토콜 Iteration protocol
ES6에서 도입된 Iterable (순회 가능한) 데이터 컬렉션을 만들기 위해 약속한 규칙이다.
이를 준수한 객체를 이터러블 이라고 한다.
이터러블은 Symbol.iterator를 프로퍼티키로 사용한 메서드를 직접 구현하거나, 프로토타입 체인을 통해 상속받은 객체를 말한다.
typeof [][Symbol.iterator] === 'function'; // true
typeof ''[Symbol.iterator] === 'function'; // true
typeof new Map()[Symbol.iterator] === 'function'; //true
typeof new Set()[Symbol.iterator] === 'function'; // true
typeof {}[Symbol.iterator] === 'function'; // false
typeof null[Symbol.iterator] === 'function'; // object null is not iterable
배열, 문자열, Map, Set 등은 이터러블이다.
for...of 문으로 순회할 수 있고, 스프레드와 배열 디스트럭처링 할당으로 사용할수있다.
빌트인 이터러블로는 Array, String, Map, Set, TypedArray, arguments, DOM 컬렉션(NodeList, HTMLCollection) 등이 있다.
const array = [1,2,3];
for(let item of array){ // for ... of 순회가능
console.log(item);
}
console.log(...array); // 1 2 3 스프레드 가능
const [a, ...rest] = array; // 배열 디스트럭처링 가능
console.log(rest) // [2, 3];
일반객체는 이터러블 프로토콜을 준수한 이터러블이 아니다
for...of 문으로 순회 불가, 배열 디스트럭처링 할당 대상으로 사용 불가.
단, TC39 프로세스 stage 4(Finished) 단계에 제안되어있는 스프레드 프로퍼티 제안은 일반 객체에 스프레드 문법 사용을 허용한다.
const obj = {a:1, b:2}
for(let item of obj){
console.log(item) // obj is not iterable... for of 순회불가
}
const [a, b] = obj; // obj is not iterable... 배열 디스트럭쳐링 불가
console.log({...obj}) // {a:1, b:2} 스프레드 가능
이터레이터
이터러블의 Symbol.iterator 메서드를 호출하면 next 메서드를 가진 이터레이터를 반환한다.
const array = [1,2,3];
const iterator = array[Symbol.iterator]();
console.log('next' in iterator); //true
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefiend, done: true}
next 메서드는 이터러블의 각 요소를 순회하기 위한 포인터 역할을 한다.
next 메서드를 호출하면, 이터러블을 순회하며 결과를 나타내는 이터레이터 리절트 객체를 반환한다.
유사배열 객체
배열처럼 인덱스로 값에 접근할수있고, length 프로퍼티를 갖는 객체.
for 문으로 순회할수있고, 인덱스로 프로퍼티 값에 접근할수있다.
이터러블이 아닌 일반 객체다. 따라서 for ... of 문으로는 순회할 수 없다.
const likeArray = {
0:1,
1:2,
length: 4
}
console.log(likeArray[1]) // 2
arguments, NodeList, HTMLCollection은 유사 배열 객체이면서 이터러블이다. (ES6에서 이터러블이 되었다!)
Array.from
Array.from 메서드를 사용하여 유사 배열 객체 또는 이터러블을 배열로 변환할 수 있다.
console.log(document.body.children); // HTMLCollection(54)
const changeIterable = Array.from(document.body.children);
무한 이터러블과 지연평가
배열이나 문자열등은 모든 데이터를 메모리를 확보한 뒤 데이터를 공급한다.
지연평가는 데이터가 필요한 시점 전까지 데이터를 생성하지 않고, 필요한 시점이 되면 데이터를 생성하는 기법이다.
for...of문이나 배열 디스트럭처링 할당이 실행되기 이전까지 데이터를 생성하지 않는다.
지연평가를 사용하면 불필요한 데이터를 미리 생성하지않고 필요한순간에 생성하므로, 메모리 낭비가 되지않으며 무한표현도 가능하다.
* 이터러블은 for ... of... memo...
스프레드 (...)
뭉쳐있는것을 펼쳐서(풀어서, spread) 목록으로 만든다. (값이 아니라 목록이다)
스프레드 문법은 for...of문으로 순회할 수 있는 이터러블에 한정된다.
일반객체는 스프레드 문법의 대상이 될 수 없다.
const obj = {a:1,b:2}
console.log(...obj) // Spread syntax requires ...iterable[Symbol.iterator] to be a function
const newObj = {...obj} // 다시 객체에 담아서 쓴다 (얕은복사)
const obj2 = {a:1,b:3,c:4}
console.log({...obj, ...obj2}) // {a: 1, b: 3, c: 4} 프로퍼티 중복시 뒤에 펼쳐진것이 우선권을 갖는다
스프레드 문법의 결과는 값이 아니라 목록이기때문에 변수에 할당할 수 없다.
const array = [1,2,3]
console.log(...array) // 1,2,3
const list = ...array; // Unexpected token '...'
const newList = [...array]; // 목록을 다시 배열에 담아서 쓴다 (얕은복사)
디스트럭처링 할당
구조분해할당은 이터러블 또는 객체를 de + structuring(구조 파괴) 하여 변수에 개별적으로 할당하는것이다.
배열 디스트럭처링 할당의 우변은 이터러블 이여야하며 할당 기준은 index이다. (순서대로 할당)
const arr = [1,2,3];
const [one,two,three] = arr; // arr에서 1을꺼내 one에 할당
console.log(one) // 1
const [a,b] = {a:1, b:2}; // {..} is not iterable
변수에 기본값을 설정할 수 있다. 이때 할당된 값이 우선한다.
const [a, b = 10, c] = [1,2,3]
console.log(a,b,c) // 1 2 3
Rest 파라미터와 유사하게 Rest 요소 ...를 사용할수있다. Rest 파라미터와 마찬가지로 마지막에 위치해야한다.
const [x, ...y] = [1,2,3];
console.log(y); // [2,3]
const [a, b, ...c] = [1,2,3];
console.log(c); // [3]
객체 디스트럭처링 할당은 프로퍼티 키를 사용한다. 순서는 의미가 없다.
const user = {name:'rumi', greeting:'hi'}
const {name, greeting: said} = user // 프로퍼티와 다른 변수이름으로 할당받을 수 있다
console.log(name) // rumi
console.log(said) // hi
const str = 'hi'
const {length} = str; // String 래퍼 객체로부터 length 프로퍼티를 추출
console.log(length) // 2
'[STUDY] 스터디 > Deep Dive JS' 카테고리의 다른 글
js 브라우저 렌더링과정 (0) | 2023.01.22 |
---|---|
js Set과 Map (0) | 2023.01.14 |
js Symbol / 변경불가능한 유일무이 값 (0) | 2023.01.12 |
js Number 그리고 Math (0) | 2023.01.03 |
js Array (0) | 2022.12.31 |