함수형 프로그래밍과 JavaScript ES6+ 강의를 수강하며 정리한 내용입니다.
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) {
log(a);
}
for (const a of str) {
log(a);
}
배열은 키를 통해 키에 매핑되는 값을 조회 가능하지만
set과 map은 불가능하므로
for...of 문은 기존 ES6의 배열 순회와 다르게 동작한다.
arr[0] // 1
set[0] // undefined
map[0] // undefined
Symbol은 어떤 객체의 key로 사용될 수 있으며
Key에는 함수가 들어있으며
null로 키를 비워버릴때 에러 발생
-> for...of 문과 symbol.iterator의 담겨져 있는 함수가 연관성이 있다.
arr[Symbol.iterator] // ƒ values() { [native code] }
set[Symbol.iterator] // ƒ values() { [native code] }
map[Symbol.iterator] // ƒ entires() { [native code] }
arr[Symbol.iterator] = null; // arr is not iterable
const arr = [1, 2, 3];
// 이터러블
arr; // [1, 2, 3]
// arr가 [Symbol.iterator]를 가지고 있다.
arr[Symbol.iterator]; // ƒ values() { [native code] }
// 실행했을 때 이터레이터를 리턴
let iterator = arr[Symbol.iterator](); // Array Iterator {}
// 이터레이터는 { value, done } 객체를 리턴하는 next() 를 가지고 있다.
iterator.next(); // {value: 1, done: false}
iterator.next(); // {value: 2, done: false}
iterator.next(); // {value: 3, done: false}
iterator.next(); // {value: undefined, done: true}
// value가 1, 2, 3 후 done이 true가 되면 순회를 멈춘다.
for (const a of iter1) log(a);
const arr = [1, 2, 3];
let iter1 = arr[Symbol.iterator](); // {value: 1, done: false}
iter1.next();
for (const a of iter1) log(a); // 2, 3
const set = new Set([1, 2, 3]);
for (const a of set) log(a);
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
// 값이 이터레이터
var it = map.values(); // [Map Iterator] { 1, 2, 3 }
// 이터레이터로 만든것이 Symbol.iterator을 가지고 있다.
// 그러므로 for...of 문에서 Symbol.iterator을 가지고 가지고 실행한다.
it[Symbol.iterator]; // ƒ [Symbol.iterator]() { [native code] }
// 자기 자신을 그대로 리턴한다.
var it2 = it[Symbol.iterator]();
it2.next(); // {value: 1, done: false}
it2.next(); // {value: 2, done: false}
it2.next(); // {value: 3, done: false}
it2.next(); // {value: undefined, done: true}
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
// 이터레이터의 key를 리턴
for (const a of map.keys()) log(a); // a, b, c
// 이터레이터의 value를 리턴
for (const a of map.values()) log(a); // 1, 2, 3
// 이터레이터의 key와 value를 리턴
for (const a of map.entries()) log(a); // ['a', 1], ['b', 2], ['c', 3]
console.clear();
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i == 0 ? {done: true} : {value: i--, done: false};
},
}
}
};
let iterator = iterable[Symbol.iterator]();
iterator.next(); // {value: 3, done: false}
iterator.next(); // {value: 2, done: false}
iterator.next(); // {value: 1, done: false}
iterator.next(); // {done: true}
for (const a of iterator) log(a);
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i == 0 ? {done: true} : {value: i--, done: false};
},
[Symbol.iterator]() {
return this;
}
}
}
};
const arr2 = [1, 2, 3];
let iter2 = arr2[Symbol.iterator]();
iter2.next();
iter2[Symbol.iterator]() == iter2;
for (const a of iter2) log(a);
for (const a of document.querySelectorAll('*')) log(a);
const all = document.querySelectorAll('*');
let iter3 = all[Symbol.iterator]();
log(iter3.next());
log(iter3.next());
log(iter3.next());
const a = [1, 2];
// a[Symbol.iterator] = null;
log([...a, ...arr, ...set, ...map.keys()]);