JavaScript - Iterable


Iterable, iterator, generator를 볼 것이다.

iterable

내부 요소들을 공개적으로 탐색(반복)할 수 있는 데이터 구조이다.

배열 ,set, map, string.

모두 Symbo.iterator라는 메소드를 가지고 있다.

const obj = {0:1, 1:2, 2:3, length:3} //유사배열 객체. not iterable

generator를 호출한 결과

function* generator(){
  yield 1
  yield 2
  yield 3
}

const gene = generator()

gene.next() // 1
gene.next() //2
gene.next() //3
gene.next() //undefined

Array.from(str)//안에 iterable한 객체를 넣으면 배열로 반환해줌. 이건 split과 같음
Array.from(gene) // [1,2,3]

spread operator 이용

[...arr]
console.log(..str)
console.log(...set)

해체 할당 가능

const [arrA,,arrC] = arr

위의 애들이 다 되는 이유는 symbol.iterator와 관련 있음

const iter = arr[Symbol.iterator](); //배열의 prototype에 정의되어 있다.

iter // Array Iterator{}

iter.next() //1
iter.next() //2
iter.next() //3
iter.next() //done:false, undefined
Array.from(iterable)
...iterable
[,,a] = iterable //해체할당
//동작 원리가 다 똑같다.

var a = iterable[Symbol.iterator]() //얘가 곧 iterator
a.next() => 반복호출. done이 true가 되기 전까지.

for(let x of iterable){

} //얘도 iterator 실행시킴.

const a = [
  new Promise((resolve, reject)=> {setTimeout(resolve, 500, 1)}), //시간 제한. 0.5초 뒤에 1이란 값을 넘겨줄 거다.
  new Promise((resolve, reject)=> {setTimeout(resolve, 100, 2)}),
  3456,
  'abc'
]

Promise.all(a) //iterable이 올 수 있음. promise이든 아니든간에 실행을 다 해버림.
  .then(v=> {console.log(v)})
  .catch(err=> {console.error(err)})
  
Promise //[1,2,3456,'abc',3]

generator - yield* 문법으로 이용 가능

const makGenerator = iterable => function*(){
  yield* iterable //=yield 1; yield 2; yield 3;
}

const aGen = makeGenerator(arr)();

aGen.next() //1
aGen.next() //2

여기까지는 모두 내부적으로 Symbol.iterator / generator를 실행하여 iterator로 변환한 상태에서 next()를 반복 호출하는 동일한 로직을 기반으로 한다.

iterable 객체에 symbol.iterator가 정의되어 있지 않은 경우

```const obj = { a: 1, b: 2, Symbol.iterator{ return 1 //안됨. 근데 반환할 수 있는 방법ㅂ이 있음 } }

iterable한 개체를 인자로 받을 수 있느 개체

new Map()
new Set()
//아래 두개 자체는 iterable 하지 않음
new WeakMap()
new WeakSet()

Promise.all()
Promise.race()
Array.from()