배열은 Symbol.iterator를 실행한 대상을 value로 떨어지는 값을 출력한다.
1) for of 일반 동작
const arr = [1, 2, 3];
for (const a of arr) console.log(a);
1, 2, 3 차례로 출력
2) for of의 Symbol.iterator를 null로
const arr = [1, 2, 3];
arr[Symbol.iterator] = null;
for (const a of arr) console.log(a);
TypeError: arr is not iterable
3) for of의 iter1.next() 한번 실행
const arr = [1, 2, 3];
let iter1 = arr[Symbol.iterator]();
console.log(iter1.next());
for (const a of iter1) console.log(a);
{ value: 1, done: false } , 2 , 3 가 각각 출력
ES6에서 나온 for of는 iterator를 만족시키는 배열, map , set과 같은 것에서 iterable을 통해 next메소드를 반복적으로 진행하며 value를 뽑아 출력하는 것이다.
이것은 iterator와 관련이 없는 for in에는 적용되지 않는다.
const arr = [1, 2, 3];
let iter1 = arr[Symbol.iterator]();
for (const a in iter1) console.log(a);
const object = {
["a"]() {},
["b"]: () => {},
};
console.log(object, object["a"], object["b"]);
{ a: [Function: a], b: [Function: b] } [Function: a] [Function: b]
결과로 같다.
iterable코드
const iterable = {
[Symbol.iterator](val) {
return {
next() {
return val == 0 ? { done: true } : { value: val--, done: false };
},
[Symbol.iterator]() {
return this;
},
};
},
};
let iterator = iterable[Symbol.iterator](3);
for (const a of iterator) console.log(a);
- next()를 반환해야한다.
[Symbol.iterator]()
는 자기자신을 리턴해야한다.
const a = [1, 2, 3];
let iter = a[Symbol.iterator]();
console.log(iter[Symbol.iterator]()[Symbol.iterator]() == iter);
console.log(iter[Symbol.iterator]() == iter);
for (const p of iter) console.log(p);
해당 iterable은 js뿐만 아니라 HTML태그에 대해서도 iterable형태가 가능하다 => for of 를 태그에서도 사용할 수 있다.
let a = [1, 2, 3];
console.log([...a]); //[ 1, 2, 3 ]
a[Symbol.iterator] = null;
console.log([...a]); //TypeError: a is not iterable
즉, 전개연산자 또한 iterable과 연관되어 있다.
const a = (...list)=>{
console.log(list)
}
a(1,2,3) // [1, 2, 3]
1,2,3 == ...list이므로
list는 배열이고 이를 ...한게 1,2,3이 되므로
list는[1,2,3]
이다.
const ex = (f) => (a, ..._) => {
console.log(a, _, f); //1 [ 2, 3, 4 ] [Function (anonymous)]
};
const mult = ex((a, b) => a * b);
mult(1, 2, 3, 4);
이터레이터이자 이터러블을 생성하는 함수
function* gen() {
yield 1;
if (false) yield 2;
yield 3;
return 100;
}
let iter = gen();
console.log(iter[Symbol.iterator]() == iter);
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
for (const a of gen()) console.log(a);
true
{ value: 1, done: false }
{ value: 3, done: false }
{ value: 100, done: true }
1
3
제너레이터 함수는 앞에
*
를 붙인다.
yield를 통해 순회할 수 있는 값을 조작한다.
if문을 통해 yield 처리도 가능하다.
return을 통해done:true
일 때 value를next()
를 이용해 확인은 가능하나
for of같은 순회에서는 확인이 불가능하다.
즉, 제너레이터를 통해 우리가 필요한 이터러블 형태를 만들어 처리할 수 있다.
...
를 하면 해당 value의 모음이 된다....iter
== 1 3