ES6μμ λμ λ μ΄ν°λ μ΄μ νλ‘ν μ½μ μν κ°λ₯ν λ°μ΄ν° 컬λ μ (μλ£κ΅¬μ‘°)λ₯Ό λ§λ€κΈ° μν΄ ECMAScript μ¬μμ μ μνμ¬ λ―Έλ¦¬ μ½μν κ·μΉμ΄λ€.
μ΄ν°λ μ΄μ νλ‘ν μ½μλ μ΄ν°λ¬λΈ νλ‘ν μ½κ³Ό μ΄ν°λ μ΄ν° νλ‘ν μ½μ΄ μλ€.
μ΄ν°λ¬λΈμ Symbol.iteratorλ₯Ό νν νΌν° ν€λ‘ μ¬μ©ν λ©μλλ₯Ό μ§μ ꡬννκ±°λ νλ‘ν νμ 체μΈμ ν΅ν΄ μμλ°μ κ°μ²΄λ₯Ό λ§νλ€.
const array = [1, 2, 3];
// λ°°μ΄μ Array.prototypeμ Symbol.iterator λ©μλλ₯Ό μμλ°λ μ΄ν°λ¬λΈμ΄λ€.
console.log(Symbol.iterator in array); // true
// μ΄ν°λ¬λΈμΈ λ°°μ΄μ for...of λ¬ΈμΌλ‘ μν κ°λ₯νλ€.
for (const item of array) {
console.log(item);
}
// μ΄ν°λ¬λΈμΈ λ°°μ΄μ μ€νλ λ λ¬Έλ²μ λμμΌλ‘ μ¬μ©ν μ μλ€.
console.log([...array]); // [1, 2, 3]
// μ΄ν°λ¬λΈμΈ λ°°μ΄μ λ°°μ΄ λμ€νΈλμ²λ§ ν λΉμ λμμΌλ‘ μ¬μ©ν μ μλ€.
const [a, ...rest] = array;
console.log(a, rest); // 1, [2, 3]
Symbol.iterator λ©μλλ₯Ό μ§μ ꡬννμ§ μκ±°λ μμλ°μ§ μμ μΌλ° κ°μ²΄λ μ΄ν°λ¬λΈ νλ‘ν μ½μ μ€μν μ΄ν°λ¬λΈμ΄ μλλ€. λ°λΌμ μΌλ° κ°μ²΄λ forβ¦of λ¬ΈμΌλ‘ μνν μ μμΌλ©° μ€νλ λ λ¬Έλ²κ³Ό λ°°μ΄ λμ€νΈλμ²λ§ ν λΉμ λμμΌλ‘ μ¬μ©ν μ μλ€.
const obj = { a: 1, b: 2 };
// μΌλ° κ°μ²΄λ Symbol.iterator λ©μλλ₯Ό ꡬννκ±°λ μμλ°μ§ μλλ€.
// λ°λΌμ μΌλ° κ°μ²΄λ μ΄ν°λ¬λΈ νλ‘ν μ½μ μ€μν μ΄ν°λ¬λΈμ΄ μλλ€.
console.log(Symbol.iterator in obj); // false
// μ΄ν°λ¬λΈμ΄ μλ μΌλ° κ°μ²΄λ for...of λ¬ΈμΌλ‘ μνν μ μλ€.
for (const item of obj) { // -> TypeError: obj is not iterable
console.log(item);
}
// μ΄ν°λ¬λΈμ΄ μλ μΌλ° κ°μ²΄λ λ°°μ΄ λμ€νΈλμ²λ§ ν λΉμ λμμΌλ‘ μ¬μ©ν μ μλ€.
const [a, b] = obj; // -> TypeError: obj is not iterable
μ΄ν°λ¬λΈμ Symbol.iterator λ©μλλ₯Ό νΈμΆνλ©΄ μ΄ν°λ μ΄ν° νλ‘ν μ½μ μ€μν μ΄ν°λ μ΄ν°λ₯Ό λ°ννλ€. μ΄ν°λ¬λΈμ Symbol.iterator λ©μλκ° λ°νν μ΄ν°λ μ΄ν°λ next λ©μλλ₯Ό κ°λλ€.
// λ°°μ΄μ μ΄ν°λ¬λΈ νλ‘ν μ½μ μ€μν μ΄ν°λ¬λΈμ΄λ€.
const array = [1, 2, 3];
// Symbol.iterator λ©μλλ μ΄ν°λ μ΄ν°λ₯Ό λ°ννλ€.
const iterator = array[Symbol.iterator]();
// Symbol.iterator λ©μλκ° λ°νν μ΄ν°λ μ΄ν°λ next λ©μλλ₯Ό κ°λλ€.
console.log('next' in iterator); // true
μ΄ν°λ μ΄ν°μ next λ©μλλ μ΄ν°λ¬λΈμ κ° μμλ₯Ό μννκΈ° μν ν¬μΈν°μ μν μ νλ€. μ¦, next λ©μλλ₯Ό νΈμΆνλ©΄ μ΄ν°λ¬λΈμ μμ°¨μ μΌλ‘ ν λ¨κ³μ© μννλ©° μνκ²°κ³Όλ₯Ό λνλ΄λ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ₯Ό λ°ννλ€.
// λ°°μ΄μ μ΄ν°λ¬λΈ νλ‘ν μ½μ μ€μν μ΄ν°λ¬λΈμ΄λ€.
const array = [1, 2, 3];
// Symbol.iterator λ©μλλ μ΄ν°λ μ΄ν°λ₯Ό λ°ννλ€. μ΄ν°λ μ΄ν°λ next λ©μλλ₯Ό κ°λλ€.
const iterator = array[Symbol.iterator]();
// next λ©μλλ₯Ό νΈμΆνλ©΄ μ΄ν°λ¬λΈμ μννλ©° μν κ²°κ³Όλ₯Ό λνλ΄λ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ₯Ό
// λ°ννλ€. μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ valueμ done νλ‘νΌν°λ₯Ό κ°λ κ°μ²΄λ€.
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: undefined, done: true }
μ΄ν°λ μ΄ν°μ next λ©μλκ° λ°νλ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄μ value νλ‘νΌν°λ νμ¬ μν μ€μΈ μ΄ν°λ¬λΈμ κ°μ λνλ΄λ©° done νλ‘νΌν°λ μ΄ν°λ¬λΈμ μν μλ£ μ¬λΆλ₯Ό λνλΈλ€.
μλ°μ€ν¬λ¦½νΈλ μ΄ν°λ μ΄μ νλ‘ν μ½μ μ€μν κ°μ²΄μΈ λΉνΈμΈ μ΄ν°λ¬λΈμ μ 곡νλ€. λ€μμ νμ€ λΉνΈμΈ κ°μ²΄λ€μ λΉνΈμΈ μ΄ν°λ¬λΈμ΄λ€.
for β¦ of λ¬Έμ μ΄ν°λ¬λΈμ μννλ©΄μ μ΄ν°λ¬λΈμ μμλ₯Ό λ³μμ ν λΉνλ€. for β¦ of λ¬Έμ for β¦ in μ νμκ³Ό λ§€μ° μ μ¬νλ€.
for (λ³μμ μΈλ¬Έ of μ΄ν°λ¬λΈ) { ... }
for (λ³μμ μΈλ¬Έ in κ°μ²΄) { ... }
for β¦ in λ¬Έμ κ°μ²΄μ νλ‘ν νμ μ²΄μΈ μμ μ‘΄μ¬νλ λͺ¨λ νλ‘ν νμ μ νλ‘νΌν° μ€μμ νλ‘νΌν° μ΄νΈλ¦¬λ·°νΈ [[Enumerable]]μ κ°μ΄ trueμΈ νλ‘νΌν°λ₯Ό μννλ©° μ΄κ±°νλ€. μ΄λ νλ‘νΌν° ν€κ° μ¬λ²μΈ νλ‘νΌν°λ μ΄κ±°νμ§ μλλ€.
for β¦ of λ¬Έμ λ΄λΆμ μΌλ‘ μ΄ν°λ μ΄ν°μ next λ©μλλ₯Ό νΈμΆνμ¬ μ΄ν°λ¬λΈμ μννλ©° next λ©μλκ° λ°νν μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄μ value νλ‘νΌν° κ°μ for β¦ of λ¬Έμ λ³μμ ν λΉνλ€. κ·Έλ¦¬κ³ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄μ done νλ‘νΌν° κ°μ΄ false μ΄λ©΄ μ΄ν°λ¬λΈμ μνλ₯Ό κ³μνκ³ trueμ΄λ©΄ μ΄ν°λ¬λΈμ μνλ₯Ό μ€λ¨νλ€.
for (const item of [1, 2, 3]) {
// item λ³μμ μμ°¨μ μΌλ‘ 1, 2, 3μ΄ ν λΉλλ€.
console.log(item); // 1 2 3
}
μ μ¬ λ°°μ΄ κ°μ²΄λ λ§μΉ λ°°μ΄μ²λΌ μΈλ±μ€λ‘ νλ‘νΌν° κ°μ μ κ·Όν μ μκ³ length νλ‘νΌν°λ₯Ό κ°λ κ°μ²΄λ₯Ό λ§νλ€. μ μ¬ λ°°μ΄ κ°μ²΄λ μ΄ν°λ¬λΈμ΄ μλ μΌλ° κ°μ²΄λ€. λ°λΌμ Symbol.iterator λ©μλκ° μκΈ° λλ¬Έμ for β¦ of λ¬ΈμΌλ‘ μνν μ μλ€.
λ¨, ES6μμ μ΄ν°λ¬λΈμ΄ λμ
λλ©΄μ μ μ¬ λ°°μ΄ κ°μ²΄μΈ arguments, NodeList, HTMLCollectionκ³Ό λ°°μ΄μ Symbol.iterator λ©μλλ₯Ό ꡬνν΄ μ΄ν°λ¬λΈμ΄ λμλ€.
ES6 μ΄μ μ μν κ°λ₯ν λ°μ΄ν° 컬λ μ (λ°°μ΄, λ¬Έμμ΄, μ μ¬ λ°°μ΄ κ°μ²΄, DOM 컬λ μ λ±)μ ν΅μΌλ κ·μ½ μμ΄ κ°μ λλ¦μ ꡬ쑰λ₯Ό κ°μ§κ³ forλ¬Έ, forβ¦inλ¬Έ, forEach λ©μλλ£ μμν λ°©λ²μΌλ‘ μνν μ μμλ€. ES6 μμλ μν κ°λ₯ν λ°μ΄ν° 컬λ μ μ μ΄ν°λ μ΄μ νλ‘ν μ½μ μ€μνλ βμ΄ν°λ¬λΈβλ‘ ν΅μΌνμ¬ forβ¦ofλ¬Έ, μ€νλ λ λ¬Έλ², λ°°μ΄ λμ€νΈλμ²λ§ ν λΉμ λμμΌλ‘ μ¬μ©ν μ μλλ‘ μΌμν νλ€.
μ΄μ²λΌ μ΄ν°λ μ΄μ νλ‘ν μ½μ λ€μν λ°μ΄ν° 곡κΈμκ° νλμ μν λ°©μμ κ°λλ‘ κ·μ νμ¬ λ°μ΄ν° μλΉμκ° ν¨μ¨μ μΌλ‘ λ€μν λ°μ΄ν° 곡κΈμλ₯Ό μ¬μ©ν μ μλλ‘ λ°μ΄ν° μλΉμμ λ°μ΄ν° 곡κΈμλ₯Ό μ°κ²°νλ μΈν°νμ΄μ€μ μν μ νλ€.
μ΄ν°λ μ΄μ νλ‘ν μ½μ μ€μνμ§ μλ μΌλ° κ°μ²΄λ μ΄λ¬ν μ΄μ νλ‘ν μ½μ μ€μνλλ‘ κ΅¬ννλ©΄ μ¬μ©μ μ μμ μ΄ν°λ¬λΈμ΄ λλ€.
// νΌλ³΄λμΉ μμ΄μ ꡬνν μ¬μ©μ μ μ μ΄ν°λ¬λΈ
const fibonacci = {
// Symbol.iterator λ©μλλ₯Ό ꡬννμ¬ μ΄ν°λ¬λΈ νλ‘ν μ½μ μ€μνλ€.
[Symbol.iterator]() {
let [pre, cur] = [0, 1]; // "36.1. λ°°μ΄ λμ€νΈλμ²λ§ ν λΉ" μ°Έκ³
const max = 10; // μμ΄μ μ΅λκ°
// Symbol.iterator λ©μλλ next λ©μλλ₯Ό μμ ν μ΄ν°λ μ΄ν°λ₯Ό λ°νν΄μΌ νκ³
// next λ©μλλ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ₯Ό λ°νν΄μΌ νλ€.
return {
next() {
[pre, cur] = [cur, pre + cur]; // "36.1. λ°°μ΄ λμ€νΈλμ²λ§ ν λΉ" μ°Έκ³
// μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ₯Ό λ°ννλ€.
return { value: cur, done: cur >= max };
}
};
}
};
// μ΄ν°λ¬λΈμΈ fibonacci κ°μ²΄λ₯Ό μνν λλ§λ€ next λ©μλκ° νΈμΆλλ€.
for (const num of fibonacci) {
console.log(num); // 1 2 3 5 8
}
μ¬μ©μ μ μ μ΄ν°λ¬λΈμ μ΄ν°λ μ΄μ νλ‘ν μ½μ μ€μνλλ‘ Symbol.iterator λ©μλλ₯Ό ꡬννκ³ Symbol.iterator λ©μλκ° next λ©μλλ₯Ό κ°λ μ΄ν°λ μ΄ν°λ₯Ό λ°ννλλ‘ νλ€. κ·Έλ¦¬κ³ μ΄ν°λ μ΄ν°μ next λ©μλλ doneκ³Ό value νλ‘νΌν°λ₯Ό κ°μ§λ μ΄ν°λ μ΄νΈ 리μ νΈ κ°μ²΄λ₯Ό λ°ννλ€. for β¦ of λ¬Έμ done νλ‘νΌν°κ° trueκ° λ λκΉμ§ λ°λ³΅νλ©° done νλ‘νΌν°κ° trueκ° λλ©΄ λ°λ³΅μ μ€μ§νλ€.
μμμ μ΄ν΄λ³Έ fibonacci μ΄ν°λ¬λΈμ λ΄λΆμ μμ΄μ μ΅λκ° maxλ₯Ό κ°μ§κ³ μλ€. μ΄ μμ΄μ μ΅λκ°μ κ³ μ λ κ°μΌλ‘ μΈλΆμμ μ λ¬λ κ°μΌλ‘ λ³κ²½ν λ°©λ²μ΄ μλ€λ μμ¬μμ΄ μλ€. μμ΄μ μ΅λκ°μ μΈμλ‘ μ λ¬λ°μ μ΄ν°λ¬λΈλ‘ λ°ννλ ν¨μλ λ€μκ³Ό κ°λ€.
// νΌλ³΄λμΉ μμ΄μ ꡬνν μ¬μ©μ μ μ μ΄ν°λ¬λΈμ λ°ννλ ν¨μ. μμ΄μ μ΅λκ°μ μΈμλ‘ μ λ¬λ°λλ€.
const fibonacciFunc = function (max) {
let [pre, cur] = [0, 1];
// Symbol.iterator λ©μλλ₯Ό ꡬνν μ΄ν°λ¬λΈμ λ°ννλ€.
return {
[Symbol.iterator]() {
return {
next() {
[pre, cur] = [cur, pre + cur];
return { value: cur, done: cur >= max };
}
};
}
};
};
// μ΄ν°λ¬λΈμ λ°ννλ ν¨μμ μμ΄μ μ΅λκ°μ μΈμλ‘ μ λ¬νλ©΄μ νΈμΆνλ€.
for (const num of fibonacciFunc(10)) {
console.log(num); // 1 2 3 5 8
}
μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°μΈ κ°μ²΄λ₯Ό μμ±νλ©΄ Symbol.iterator λ©μλλ₯Ό νΈμΆνμ§ μμλ μ΄ν°λ μ΄ν°λ₯Ό μμ±ν μ μλ€. λ€μ κ°μ²΄λ Symbol.iterator λ©μλμ next λ©μλλ₯Ό μμ ν μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°λ€. Symbol.iterator λ©μλλ thisλ₯Ό λ°ννλ―λ‘ next λ©μλλ₯Ό κ°λ μ΄ν°λ μ΄ν°λ₯Ό λ°ννλ€.
// μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°μΈ κ°μ²΄. μ΄ν°λ μ΄ν°λ₯Ό λ°ννλ Symbol.iterator λ©μλμ
// μ΄ν°λ μ΄μ
리μ νΈ κ°μ²΄λ₯Ό λ°ννλ next λ©μλλ₯Ό μμ νλ€.
{
[Symbol.iterator]() { return this; },
next() {
return { value: any, done: boolean };
}
}
// μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°μΈ κ°μ²΄λ₯Ό λ°ννλ ν¨μ
const fibonacciFunc = function (max) {
let [pre, cur] = [0, 1];
// Symbol.iterator λ©μλμ next λ©μλλ₯Ό μμ ν μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°μΈ κ°μ²΄λ₯Ό λ°ν
return {
[Symbol.iterator]() { return this; },
// next λ©μλλ μ΄ν°λ μ΄ν° 리μ νΈ κ°μ²΄λ₯Ό λ°ν
next() {
[pre, cur] = [cur, pre + cur];
return { value: cur, done: cur >= max };
}
};
};
// iterλ μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°λ€.
let iter = fibonacciFunc(10);
// iterλ μ΄ν°λ¬λΈμ΄λ―λ‘ for...of λ¬ΈμΌλ‘ μνν μ μλ€.
for (const num of iter) {
console.log(num); // 1 2 3 5 8
}
// iterλ μ΄ν°λ¬λΈμ΄λ©΄μ μ΄ν°λ μ΄ν°λ€
iter = fibonacciFunc(10);
// iterλ μ΄ν°λ μ΄ν°μ΄λ―λ‘ μ΄ν°λ μ΄μ
리μ νΈ κ°μ²΄λ₯Ό λ°ννλ next λ©μλλ₯Ό μμ νλ€.
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: 5, done: false }
console.log(iter.next()); // { value: 8, done: false }
console.log(iter.next()); // { value: 13, done: true }
무ν μ΄ν°λ¬λΈμ μμ±νλ ν¨μλ 무ν μμ΄μ κ°λ¨ν ꡬνν μ μλ€.
// 무ν μ΄ν°λ¬λΈμ μμ±νλ ν¨μ
const fibonacciFunc = function () {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() { return this; },
next() {
[pre, cur] = [cur, pre + cur];
// 무νμ ꡬνν΄μΌ νλ―λ‘ done νλ‘νΌν°λ₯Ό μλ΅νλ€.
return { value: cur };
}
};
};
// fibonacciFunc ν¨μλ 무ν μ΄ν°λ¬λΈμ μμ±νλ€.
for (const num of fibonacciFunc()) {
if (num > 10000) break;
console.log(num); // 1 2 3 5 8...4181 6765
}
// λ°°μ΄ λμ€νΈλμ²λ§ ν λΉμ ν΅ν΄ 무ν μ΄ν°λ¬λΈμμ 3κ°μ μμλ§ μ·¨λνλ€.
const [f1, f2, f3] = fibonacciFunc();
console.log(f1, f2, f3); // 1 2 3
μ μμ μ μ΄ν°λ¬λΈμ μ§μ° νκ°λ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό μμ±νλ€. μ§μ° νκ°λ λ°μ΄ν°κ° νμν μμ μ΄μ κΉμ§λ 미리 λ°μ΄ν°λ₯Ό μμ±νμ§ μλ€κ° λ°μ΄ν°κ° νμν μμ μ΄ λλ©΄ κ·ΈλμΌ λΉλ‘μ λ°μ΄ν°λ₯Ό μμ±νλ κΈ°λ²μ΄λ€. μ¦, νκ° κ²°κ³Όκ° νμν λκΉμ§ νκ°λ₯Ό λ¦μΆλ κΈ°λ²μ΄ μ§μ° νκ°λ€.