const list = [1, 2, 3];
for( var i = 0; i< list.length; i++){
log(list[i]);
}
/*유사 배열 순회*/
const str = 'abc';
for( var i = 0; i< str.length; i++){
log(str[i]);
}
for(const a of list){ //for of로 리스트 안에 있는 값(a)을 순회한다.
log(a);
}
for(const a of str){
log(a);
}
이터러블을 for...of, 전개 연산자 등과 함께 동작하도록 한 규약을 말한다.
// Array
const arr = [1, 2, 3];
for(const a of arr) log(a);
// Set
const set = new Set([1,2,3]);
for(const a of set) log(a);
// Map
const map = new Map([['a',1], ['b', 2], ['c', 3]]);
for (const a of map)log(a)
이터러블
: 이터레이터를 리턴하는 Symbol.iterator() 를 가진 값
이터레이터
: {value, done} 객체를 리턴하는 next() 를 가진 값
map이 아닌 map.values(), map.keys(), map.entries()역시 정상동작을 하는데, 이는 해당 함수를 통해 반환되는 값들도 Iterator 형태임을 알 수 있다.
Array, Set, Map은 Javascript 내장객체로써 이터러블/이터레이터 프로토콜을 따른다.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next(){
return i == 0 ? {done: true}:{value: i--, done:false};
},
[Symbol.iterator](){return this;} //자기자신을 return 해준다.
}
}
}
let iterator = iterable[Symbol.iterator]();
iterator.next(); // 주석 처리하며 비교해보자.
for(const a of iterator) console.log(a);
이터레이터 역시 Symbol.iterator를 가지고 있고 이 Symbol.iterator를 실행한 값은 자기자신이다.
const arr2 = [1, 2, 3];
let iter = arr2[Symbol.iterator]();
log(iter[Symbol.iterator]() == iter2)// true
for( const a of document.querySelectorAll('*')) log(a) //dom ... dom
querySelectorAll의 반환값(NodeList)역시 Symbol.iterator가 구현되어 있고 규약을 따르기에 for...of 사용을 통해 순회가 가능하다.
const a = [1, 2];
a[Symbol.iterator] = null;
log([...a, ...[3,4]);//Uncaught TypeError: a is not iterable
const b = [1, 2];
log([...a, ...[3,4]); // [1, 2, 3, 4]
a[Symbol.iterator] = null; 으로 iterator를 null로 해주면 에러가 발생한다.
즉, 전개연산자 역시 iterable 프로토콜을 따른다는 의미가 된다.