[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ดํฐ๋ฌ๋ธ Iterable ์ด ์ ๋ฆฌ
TL;DR โญ๏ธ
Symbol.iterator
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์๋ ๊ฐ์ฒด๋ฅผ ์ดํฐ๋ฌ๋ธ(iterable)์ด๋ผ๊ณ ํ๋ค. ๊ฐ๋จํ ๋งํ๋ฉด ์ดํฐ๋ฌ๋ธ์ ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด๋ค. ๋ฐฐ์ด, ๋ฌธ์์ด์Symbol.iterator
๋ฉ์๋๊ฐ ์ด๋ฏธ ๊ตฌํ๋์ด ์๋ ๋ํ์ ์ธ ๋ด์ฅ ์ดํฐ๋ฌ๋ธ์ด๋ค. ์ดํฐ๋ฌ๋ธ์ ์ฌ์ฉํ๋ฉด ์ด๋ค ๊ฐ์ฒด๋ โfor of
๋ฐ๋ณต๋ฌธ โ์ ๊ฐ ๋ฌธ๋ฒ โ๋ฐฐ์ด ๊ตฌ์กฐ๋ถํด ํ ๋น์ ๋์์ผ๋ก ์ฌ์ฉํ ์๋ ์๋ค.
โถ for of
๋ฌธ์ ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์ดํฐ๋ฌ๋ธ์ด๋ผ๊ณ ํ๋ค
โท ์ดํฐ๋ฌ๋ธ์ Symbol.iterator
๋ฉ์๋(ํน์ ํ๋กํ ํ์
์ฒด์ธ์ ์ํด ์์)๊ฐ ๊ตฌํ๋์ด ์์ด์ผ ํ๋ค.
Symbol.iterator
๋for of
์ ์ํด ์๋์ผ๋ก ํธ์ถ๋๋ฉฐ, ๋ช ์์ ์ผ๋ก ํธ์ถํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋คSymbol.iterator
๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด๋ “์ดํฐ๋ ์ดํฐ”๋ผ๊ณ ๋ถ๋ฅธ๋ค- ์ดํฐ๋ ์ดํฐ๋ ๋ฐ๋ณต ๊ณผ์ ์ ์ฒ๋ฆฌํ๋ฉฐ,
for of
๋ฌธ์ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ง์ ๋์์ผ๋ก ๋์ํ๋ค - ์ดํฐ๋ ์ดํฐ ์์๋ ๋ฐ๋ณต ๋์ ๊ฐ์ฒด
{ done: Boolean, value: any }
๋ฅผ ๋ฐํํ๋next()
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์์ด์ผ ํ๋ค.done
์์ฑ : ๋ฐ๋ณต์ ์ข ๋ฃ ์ฌ๋ถvalue
์์ฑ : ํ์ฌ ์ํ์ค์ธ ์ดํฐ๋ฌ๋ธ์ ๊ฐfor of
๋ฌธ์์ ๊ฐ์ ์ํํ ๋๋ง๋คnext()
๋ฉ์๋๋ฅผ ํธ์ถํด์value
๋ฅผ ๊ฐ์ ธ์จ๋ค
โธ ๋ฌธ์์ด, ๋ฐฐ์ด ๊ฐ์ ๋ด์ฅ ์ดํฐ๋ฌ๋ธ์ Symbol.iterator
๊ฐ ๊ตฌํ๋์ด ์๋ค. ์ด๋ค์ ๋ชจ๋ ์ดํฐ๋ฌ๋ธ์ด๋ค.
console.log(Symbol.iterator in Array.prototype); // true
console.log(Symbol.iterator in String.prototype); // true
console.log(Symbol.iterator in Object.prototype); // false
โน ์ ์ฌ ๋ฐฐ์ด์ ์ธ๋ฑ์ค์ length
ํ๋กํผํฐ๋ฅผ ๊ฐ์ง, ๋ฐฐ์ด์ฒ๋ผ ๋ณด์ด๋ ๊ฐ์ฒด๋ค. ์ดํฐ๋ฌ๋ธ๊ณผ๋ ๋ค๋ฅด๋ฏ๋ก ์ฃผ์.
โบ Array.from
๋ฉ์๋๋ฅผ ์ด์ฉํด ์ ์ฌ ๋ฐฐ์ด๊ณผ ์ดํฐ๋ฌ๋ธ์ ์ง์ง ๋ฐฐ์ด๋ก ๋ง๋ค ์ ์๋ค.
Symbol.iterator — ๋๊ธฐ ์ดํฐ๋ ์ดํฐ
๐ก ๋ฐ์ดํฐ ์ปฌ๋ ์
์ ์ํํ๊ธฐ ์ํด ์ดํฐ๋ ์ด์
ํ๋กํ ์ฝ(๊ท์น)์ด ES6์ ๋์
๋๋ค. ์ดํฐ๋ ์ด์
ํ๋กํ ์ฝ์ ์ค์ํ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ดํฐ๋ฌ๋ธ์ Symbol.iterator
๋ฉ์๋๋ฅผ ์ง์ ๊ตฌํํ๊ฑฐ๋, ํ๋กํ ํ์
์ฒด์ธ์ ์ํด Symbol.iterator
๋ฉ์๋๋ฅผ ์์๋ฐ์ ๊ฐ์ฒด๋ฅผ ๋งํ๋ค.
์ดํฐ๋ฌ๋ธ์ for of
๋ฐ๋ณต๋ฌธ / ์ ๊ฐ ๋ฌธ๋ฒ / ๋ฐฐ์ด ๊ตฌ์กฐ๋ถํด ํ ๋น์ ๋์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. ๋ฐฐ์ด, ๋ฌธ์์ด ๋ฑ์ Symbol.iterator
๋ฉ์๋๋ฅผ ์์ ํ๋ฏ๋ก ์ดํฐ๋ฌ๋ธ ํ๋กํ ์ฝ์ ์ค์ํ ์ดํฐ๋ฌ๋ธ์ด๋ค. ๋ฐ๋ผ์ ์ด๋ค์ ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด์ด๋ค.
์ดํฐ๋ฌ๋ธ
๋ฐฐ์ด์ Symbol.iterator
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์๋ ์ดํฐ๋ฌ๋ธ์ด๋ค. Symbol.iterator
๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํน์ํ ๋ด์ฅ ์ฌ๋ณผ์ด๋ฉฐ, ํธ์ถํ๋ฉด ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค. ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ next()
๋ผ๋ ๋ฉ์๋๋ฅผ ๊ฐ๋๋ค.
next()
๋ฅผ ํธ์ถํ ๋๋ง๋ค ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ์ํํ์ฌ value
, done
ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด(๋ฐ๋ณต ๋์ ๊ฐ์ฒด ํน์ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๋ผ๊ณ ๋ถ๋ฅธ๋ค)๋ฅผ ๋ฐํํ๋ค. value
์์ฑ์ ํ์ฌ ์ํํ๋ ์์์ ๊ฐ์ ๋ํ๋ธ๋ค.
// ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ช
์์ ์ผ๋ก ํธ์ถํ ์์
const array = [1, 2, 3]; // ๋ฐฐ์ด์ ์ดํฐ๋ฌ๋ธ ํ๋กํ ์ฝ์ ์ค์ํ ์ดํฐ๋ฌ๋ธ์ด๋ค
const iterator = array[Symbol.iterator](); // next ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ
// next() ๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๋ value์ done ํ๋กํผํฐ๋ฅผ ๊ฐ๋๋ค
iterator.next(); // { value: 1, done: false }
iterator.next(); // { value: 2, done: false }
iterator.next(); // { value: 3, done: false }
iterator.next(); // { value: undefined, done: true }
์ ์ฝ๋์์ โSymbol.iterator
๋ฉ์๋ ํธ์ถ → โ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ → โ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด์ next()
๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ณผ์ ์ ์๋ ๋ฐ๋ณต๋ฌธ์ด ์๋ํ๋ ๊ฒ๊ณผ ๋์ผํ๋ค.
const array = [1, 2, 3];
for (const num of array) {
console.log(num); // 1, 2, 3
}
์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด
์๋ range
๋ณ์๋ ์ซ์ ๊ฐ๊ฒฉ์ from
(1)๊ณผ to
(5) ์์ฑ์ผ๋ก ๋ํ๋ด๊ณ ์๋ ์ผ๋ฐ์ ์ธ ๊ฐ์ฒด๋ค. ์ผ๋ฐ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ์ด ์๋๋ฏ๋ก ๋ฐ๋ณต๋ฌธ์ ๋๋ฆฌ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ํ์ง๋ง Symbol.iterator
๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฐ๋ณต ๊ฐ๋ฅํ(์ดํฐ๋ฌ๋ธ) ๊ฐ์ฒด๋ก ๋ง๋ค ์ ์๋ค.
const range = { from: 1, to: 5 };
for (const num of range) {
console.log(num); // Error! range is not iterable
}
range
๊ฐ์ฒด์ Symbol.iterator
๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ณ , ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด next()
๋ฉ์๋๋ฅผ ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ๋๋ค. for of
๋ฐ๋ณต๋ฌธ์ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ง์ ๋์์ผ๋ก ๋์ํ๋ค.
// ์ฝ๋ ์ฐธ๊ณ JavaScript Info
// โด for of ์์ ์ Symbol.iterator ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค
range[Symbol.iterator] = function () {
// โต Symbol.iterator๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ๋๋ค
// for of ๋ฌธ์ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ด๋ค
return {
current: this.from,
last: this.to,
// โถ for of ๋ฌธ์ ์ํํ ๋๋ง๋ค next() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค
next() {
// โท next()๋ { done: Boolean, value: any } ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ๋๋ค
if (this.current <= this.last) {
return { done: false, value: this.current++ };
// current++๋ ํ์ ์ฆ๊ฐ ์ฐ์ฐ์๋ฏ๋ก ์ฆ๊ฐํ๊ธฐ ์ ๊ฐ์ ๋ฐํํด์ value ์์ฑ์ ํ ๋น๋๋ค
} else {
return { done: true };
}
},
};
};
๋ค์ for of
๋ฌธ์ ์คํํด๋ณด๋ฉด ์ ์์ ์ผ๋ก ๋์ํ๋ค.
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
๐ก ์ ๋ฆฌํ๋ฉด Symbol.iterator
๋ฅผ ํธ์ถํด์ ๋ฐํํ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด์, ์ด ๊ฐ์ฒด ์์ ์ ์ํ next()
๋ฉ์๋์ ์ํด ๋ฐ๋ณต๋ฌธ์์ ์ฌ์ฉํ ๊ฐ์ ๋ง๋ค์ด๋ด๋ ๊ตฌ์กฐ๋ค.
for of
๋ฐ๋ณต๋ฌธ ์์ →Symbol.iterator
ํธ์ถ → ๋ฐํ๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ๋์Symbol.iterator
๊ฐ ์์ผ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋คSymbol.iterator
๋ ํญ์next()
ํจ์๊ฐ ํฌํจ๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ๋๋ค. โก๏ธ
for of
๋ฐ๋ณต๋ฌธ์ ์ํํ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ ์ํดnext()
๋ฉ์๋ ํธ์ถnext()
๋ฉ์๋์ ๋ฐํ๊ฐ์{ done: Boolean, value: any }
ํํ์ ๊ฐ์ฒด์ฌ์ผ ํ๋ค. โกdone
์์ฑ์ ๋ฐ๋ณต์ ์ข ๋ฃ ์ฌ๋ถ๋ฅผ ๋ํ๋ธ๋ค.value
์์ฑ์ ํ์ฌ ์ํ์ค์ธ ์ดํฐ๋ฌ๋ธ์ ๊ฐ์ด๋ค.
๊ฐ์ฒด ์์ฒด๋ฅผ ์ดํฐ๋ ์ดํฐ๋ก ๋ง๋ค๊ธฐ
range
๊ฐ์ฒด ์์ฒด๋ฅผ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด(range[Symbol.iterator]()
๋ฐํ๊ฐ)์ ๋ฐ๋ณต ๋์ ๊ฐ์ฒด(next()
๋ฐํ๊ฐ)๋ฅผ ํฌํจํ๋ ์ดํฐ๋ ์ดํฐ๋ก ๋ง๋ค๋ฉด ์ฝ๋๋ฅผ ๋ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์ ์๋ค.
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
๐ก range.to
์ Infinity
๋ฅผ ํ ๋นํ๋ฉด range
๋ ๋ฌดํ๋๊ฐ ๋๋ค. ๋ง์ ๋์๋ฅผ ์์ฑํด์ผ๋ ๋ ์ ์ฉ.
for of
๋ฐ๋ณต๋ฌธ ์์range[Symbol.iterator]()
๋ฉ์๋ ํธ์ถrange
๊ฐ์ฒด ๋ฐํ. ์ด ๊ฐ์ฒด์ ์๋ 2๊ฐ๋ฅผ ๋ชจ๋ ํฌํจํ๋ฏ๋กfor of
๋ฌธ๋ ์ ์๋ํ๋ค.- ๋ฐ๋ณต ๋์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํ์ ๋ฉ์๋
next()
- ๋ฐ๋ณต ์งํ ์ํ๋ฅผ ๋ํ๋ด๋
this.current
- ๋ฐ๋ณต ๋์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํ์ ๋ฉ์๋
๋ช ์์ ์ผ๋ก ์ดํฐ๋ ์ดํฐ ํธ์ถํ๊ธฐ
๋ฌธ์์ด๋ ์ดํฐ๋ฌ๋ธ์ด๋ค. ๋ฐ๋ผ์ for of
๋ฌธ์ผ๋ก ์ํํ ์ ์๋ค.
const str = 'hello';
for (const letter of str) console.log(letter); // h e l l o
๋ฌธ์์ด์ ๋ํ ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ง๋ค๊ณ , ์ด๋ฅผ ์ง์ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์์ด์ ์ํํ ์๋ ์๋ค. ๋ฐ๋ณต ์์ → ๋ฐ๋ณต ์ค์ง → ๋ค๋ฅธ ์์ ์ํ → ๋ค์ ๋ฐ๋ณต ํ๋ ๋ฐฉ์์ผ๋ก ๋ฐ๋ณต ๊ณผ์ ์ ์ชผ๊ฐค ์ ์๋ ์ฅ์ ์ด ์๋ค.
const str = 'hello';
const iterator = str[Symbol.iterator](); // StringIterator {}
while (true) {
const { value, done } = iterator.next();
if (done) break;
console.log(value); // h e l l o
}
์ปค์คํ ์ดํฐ๋ฌ๋ธ๋ก ํผ๋ณด๋์น ๊ตฌํํ๊ธฐ โญ๏ธ
๐ก ๋ฐฐ์ด์ด๋ ๋ฌธ์์ด ๋ฑ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ํ๋ณดํ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ๊ณต๊ธํ๋ค. ๋ฐ๋ฉด ์ดํฐ๋ฌ๋ธ์ ์ฌ์ฉํ๋ฉด ์ดํฐ๋ฌ๋ธ์ด ๋ฐ์ดํฐ ๊ณต๊ธ์ ์ญํ ์ ํ๋ฉฐ, ์ง์ฐ ํ๊ฐ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ค. ์ง์ฐ ํ๊ฐ๋ ๋ฐ์ดํฐ๊ฐ ํ์ํ ์์ ์ด ๋ ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ๊ธฐ๋ฒ์ด๋ค. ์ง์ฐ ํ๊ฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋นํ์ง ์๊ณ , ๋ฌดํ๋ ํํํ ์ ์๋ ์ฅ์ ์ด ์๋ค.
์ผ๋ฐ ๊ฐ์ฒด๋ฅผ ์ดํฐ๋ฌ๋ธ๋ก ๋ง๋ค์ด์ ํผ๋ณด๋์น ์์ด(1, 2, 3, 5, 8, ...)์ ๋ฐํํ๋ ๊ฐ์ฒด๋ฅผ ๊ตฌํํ ์ ์๋ค.
// ํผ๋ณด๋์น ์์ด์ ๋ฐํํ๋ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด
const fibonacci = {
// Symbol.iterator ๋ฉ์๋๋ฅผ ๊ตฌํํด์ ์ดํฐ๋ฌ๋ธ ํ๋กํ ์ฝ์ ์ค์ํ๋ค
[Symbol.iterator]() {
let [pre, cur] = [0, 1];
const max = 10; // ์ต๋๊ฐ
// Symbol.iterator ๋ฉ์๋๋ next ๋ฉ์๋๋ฅผ ํฌํจํ "์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด"๋ฅผ ๋ฐํํ๋ค
return {
// fibonacci ๊ฐ์ฒด๋ฅผ ์ํํ ๋๋ง๋ค next ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค
// next ๋ฉ์๋๋ "์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด"๋ฅผ ๋ฐํํ๋ค
next() {
[pre, cur] = [cur, pre + cur]; // [1, 1] [1, 2] [2, 3] [3, 5] ...
return {
value: cur,
done: cur >= max,
};
},
};
},
};
// fibonacci ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ ํ๋กํ ์ฝ์ ์ค์ํ์ผ๋ฏ๋ก for of ๋ฌธ์ผ๋ก ์ํํ ์ ์๋ค
for (const num of fibonacci) {
// for of ๋ฌธ์ done ํ๋กํผํฐ๊ฐ true๊ฐ ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
// for of ๋ด๋ถ์์ break ๋ฌธ์ ์ฌ์ฉํ ์ ์๋ค. *ex) if (num >= 10) break;*
console.log(num); // 1 2 3 5 8
// 13๋ถํฐ max ๊ฐ(10) ์ด์์ด๋ฏ๋ก done ํ๋กํผํฐ๊ฐ true๊ฐ ๋ผ์ ๋์ด์ ์ํํ์ง ์๋๋ค
}
// spread ๋ฌธ๋ฒ(์ ๊ฐ์ฐ์ฐ์)์ ์ด์ฉํด ์ดํฐ๋ฌ๋ธ์ ๋ฐฐ์ด๋ก ๋ณํํ ์ ์๋ค
const fiboNum = [...fibonacci]; // [1, 2, 3, 5, 8]
// ์ดํฐ๋ฌ๋ธ์ spread ๋ฌธ๋ฒ, ๊ตฌ์กฐ๋ถํดํ ๋น, Map/Set ์์ฑ์์๋ ์ฌ์ฉ๋๋ค
const [first, second, ...rest] = fibonacci; // 1 2 [3, 5, 8]
์ ์์ ์ ์ดํฐ๋ฌ๋ธ์ ์ธ๋ถ์์ ์ต๋ ๋ฐ๋ณต ํ์๋ฅผ ์ง์ ํ ์ ์๋ค. ์ด๋ฅผ ๊ฐ์ ํ๋ ค๋ฉด ์ต๋ ๋ฐ๋ณต ํ์์ธ max
๋ฅผ ์ธ์๋ก ๋ฐ์ ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ์ธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋ง๋ค๋ฉด ๋๋ค. ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ผ๋ฏ๋ก Symbol.iterator
๋ฉ์๋๋ฅผ ํธ์ถํ์ง ์์๋ ๋๋ค(์์ฑํ ๊ฐ์ฒด์ next
๋ฉ์๋๊ฐ ์ด๋ฏธ ๊ตฌํ๋์ด ์์ผ๋ฏ๋ก).
// ์๋ ๊ฐ์ฒด๋ Symbol.iterator, next ๋ฉ์๋๋ฅผ ๋ชจ๋ ์์ ํ์ผ๋ฏ๋ก ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ๋ค
{
[Symbol.iterator]() { return this; }, // next ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๋ฐํ
next() { /* ... */ }
}
// ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ์ธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ fibonacci ํจ์
const fibonacci = (max) => {
let [pre, cur] = [0, 1];
return {
// ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ์ธ ๊ฐ์ฒด ๋ฐํ
[Symbol.iterator]() {
return this;
},
next() {
[pre, cur] = [cur, pre + cur]; // [1, 1] [1, 2] [2, 3] [3, 5] ...
return { value: cur, done: cur >= max }; // ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด ๋ฐํ
},
};
};
// iter๋ ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ
let iter = fibonacci(10);
// ์ฌ๊ธฐ์ iter๋ ์ดํฐ๋ ์ดํฐ
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
iter = fibonacci(20);
// ์ฌ๊ธฐ์ iter๋ ์ดํฐ๋ฌ๋ธ
for (const num of iter) console.log(num); // 1 2 3 5 8 13
next()
๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ done
ํ๋กํผํฐ๋ฅผ ์๋ตํด์ ๋ฌดํ ์ดํฐ๋ฌ๋ธ(๋ฌดํ์ ํผ๋ณด๋์น ์์ด ์์ฑ)์ ๊ตฌํํ ์๋ ์๋ค.
// ๋ฌดํ ์ดํฐ๋ฌ๋ธ์ ์์ฑํ๋ fibonacci ํจ์
const fibonacci = () => {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() {
return this;
},
next() {
[pre, cur] = [cur, pre + cur]; // [1, 1] [1, 2] [2, 3] [3, 5] ...
return { value: cur }; // done ํ๋กํผํฐ ์๋ต
},
};
};
for (const num of fibonacci()) {
if (num > 1000) break;
console.log(num); // 1 2 3 5 8 13 ...
}
const [f1, f2, f3] = fibonacci(); // ๊ตฌ์กฐ๋ถํดํ ๋น์ ์ด์ฉํด 3๊ฐ ์์๋ง ๊ฐ์ ธ์ฌ ์ ์๋ค
console.log(f1, f2, f3); // 1 2 3
(๋ฒ์ธ) ES6์์ ์ ๊ณตํ๋ ๋นํธ์ธ ์ดํฐ๋ฌ๋ธ ๋ชฉ๋ก
์๋ ํญ๋ชฉ๋ค์ ๋ชจ๋ Symbol.iterator
๋ฉ์๋๋ฅผ ์์ ํ ์ดํฐ๋ฌ๋ธ์ด๋ฏ๋ก for of
๋ฌธ์ผ๋ก ์ํํ ์ ์๋ค.
๋นํธ์ธ ์ดํฐ๋ฌ๋ธ | Symbol.iterator ๋ฉ์๋ |
Array | Array.prototype[Symbol.iterator] |
String | String.prototype[Symbol.iterator] |
Map | Map.prototype[Symbol.iterator] |
Set | Set.prototype[Symbol.iterator] |
TypedArray | TypedArray.prototype[Symbol.iterator] |
arguments | arguments[Symbol.iterator] |
DOM ์ปฌ๋ ์ | NodeList.prototype[Symbol.iterator] HTMLCollection.prototype[Symbol.iterator] |
์ดํฐ๋ฌ๋ธ๊ณผ ์ ์ฌ ๋ฐฐ์ด
- ์ดํฐ๋ฌ๋ธ(iterable) :
Symbol.iterator
๋ฉ์๋๊ฐ ๊ตฌํ๋ ๊ฐ์ฒด - ์ ์ฌ ๋ฐฐ์ด(array-like) : ์ธ๋ฑ์ค์
length
ํ๋กํผํฐ๋ฅผ ๊ฐ์ง, ๋ฐฐ์ด์ฒ๋ผ ๋ณด์ด๋ ๊ฐ์ฒด
์๋ arrayLike
๋ ์ธ๋ฑ์ค์ length
์์ฑ์ ๊ฐ์ง๋ฏ๋ก ์ ์ฌ ๋ฐฐ์ด์ด์ง๋ง, ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ ์๋๋ค. ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๊ฐ ์๋๋ฏ๋ก for of
๋ฌธ๋ ์ฌ์ฉํ ์ ์๋ค. ๋ฐ๋ฉด ์ ์์์ range ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ length
์ ์ธ๋ฑ์ค ์์ฑ์ด ์์ผ๋ฏ๋ก ์ ์ฌ ๋ฐฐ์ด์ด ์๋๋ค.
๐ก ์์ธ์ ์ผ๋ก arguments, NodeList, HTMLCollection์ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด๋ฉด์ ์ดํฐ๋ฌ๋ธ์ด๋ค.
const arrayLike = {
0: 'Hello',
1: 'World',
length: 2,
};
for (const el of arrayLike) {
} // Error! arrayLike is not iterable
arrayLike.push(2); // arrayLike.push is not a function
์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด์ ์ ์ฌ ๋ฐฐ์ด(๊ฐ์ฒด)์ ๋ฐฐ์ด์ด ์๋๋ฏ๋ก push
, pop
๊ฐ์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ดํฐ๋ฌ๋ธ / ์ ์ฌ๋ฐฐ์ด์์ ๋ฐฐ์ด ๋ฉ์๋ ์ฌ์ฉํ๊ธฐ
Array.from
Array.from
๋ฉ์๋๋ โ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ โ์ ์ฌ ๋ฐฐ์ด์ ๋ฐ์ ์ง์ง ๋ฐฐ์ด(Array)์ ๋ง๋ ๋ค. ๊ทธ๋ผ push
๊ฐ์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค. Array.from
์ ๋๊ฒจ๋ฐ์ ์ธ์๊ฐ ์ดํฐ๋ฌ๋ธ ํน์ ์ ์ฌ ๋ฐฐ์ด์ด๋ฉด ๊ฐ์ฒด๋ด ๋ชจ๋ ์์๋ฅผ ์๋ก์ด ๋ฐฐ์ด๋ก ๋ณต์ฌํ๋ค(์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ๋๊ธฐ๋ฉด next()
๋ฉ์๋๊ฐ ๋ฐํํ ๋ชจ๋ value
๊ฐ์ด ์๋ก์ด ๋ฐฐ์ด์ ์์๋ก ์ถ๊ฐ๋๋ค).
// ์ ์ฌ ๋ฐฐ์ด
const arrayLike = {
0: 'Hello',
1: 'World',
length: 2,
};
// [์ ์ฌ ๋ฐฐ์ด -> ๋ฐฐ์ด]
const arrayFromArrayLike = Array.from(arrayLike); // ['Hello', 'World']
arrayFromArrayLike.push('JavaScript');
console.log(arrayFromArrayLike); // ['Hello', 'World', 'JavaScript']
// [์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด -> ๋ฐฐ์ด]
// range๋ ์ ์์ ์ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด
const arrayFromIterable = Array.from(range); // [1, 2, 3, 4, 5]
์ ์ฌ ๋ฐฐ์ด์์ length
์์ฑ ๊ฐ ๋งํผ ๋ณต์ฌํ ์์๋ฅผ ์๋ก์ด ๋ฐฐ์ด์ ์ถ๊ฐํ๋ค. ์์ ๊ฐ์๋ณด๋ค ๋ง์ length
๋ฅผ ์
๋ ฅํ๋ค๋ฉด, length
์์น์ ๋์ํ๋ ์์๊ฐ ์์๋ undefined
๊ฐ ๋ฐฐ์ด์ ๋ด๊ธฐ๋ฏ๋ก ์ฃผ์ํ๋ค.
๐ก Array.from
์ฒซ๋ฒ์งธ ์ธ์์ ํน์ ๊ธธ์ด๋ฅผ ๊ฐ๋ ๋ฐฐ์ด์ ๋๊ธธ ๋ Array(n)
๋์ { length: n }
ํํ๋ก ๋๊ธธ ์๋ ์๋คex) Array.from({ length: 2 })
→ [undefined, undefined]
const arrayLike = {
0: 'Hello',
1: 'World',
length: 4,
};
Array.from(arrayLike); // ['Hello', 'World', undefined, undefined]
Array.from ๋งคํ ํจ์
Array.from(arrayLike[, mapFn[, thisArg]])
Array.from
๋๋ฒ์งธ ์ธ์๋ ๋งคํ ํจ์๋ฅผ ๋ฐ๋๋ค. ๋งคํ ํจ์๋ฅผ ๋๊ธฐ๋ฉด ๊ฐ์ฒด์ ๊ฐ ์์๋ฅผ ๋์์ผ๋ก ํด๋น ๋งคํ ํจ์๊ฐ ์ ์ฉ๋ ๊ฐ์ด ์๋ก์ด ๋ฐฐ์ด์ ๋ด๊ธด๋ค. thisArg
๋ ๊ฐ ์์์ this
๋ฅผ ์ง์ ํ ๋ ์ฌ์ฉํ๋ค.
// range๋ ์ ์์ ์ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด
Array.from(range); // ๋งคํ ํจ์ ์ ์ฉ ์ [1, 2, 3, 4, 5]
Array.from(range, num => num * 2); // ๋งคํ ํจ์ ์ ์ฉ ํ [2, 4, 6, 8, 10]
Array.from
์ ๊ฐ์ฒด๊ฐ ๊ฐ์ง ์ดํฐ๋ฌ๋ธ ์์ฑ์ ์ด์ฉํด ๋์ํ๋ฉฐ, ๋ด๋ถ์์ ์๋์ ๋์ผํ ๋ฐ๋ณต๋ฌธ์ด ๋์๊ฐ๋ค.
// Array.from ๋ด๋ถ๋ ์๋์ ๋์ผํ ๋ฐ๋ณต๋ฌธ์ด ์๋ํ๋ค
const arr = [];
for (const num of range) {
arr.push(num);
}
console.log(arr); // [1, 2, 3, 4, 5]
Array.from
๋ ์ดํฐ๋ฌ๋ธ ์์ฑ์ ์ด์ฉํด ๋์ํ๋ฏ๋ก ๋ฌธ์์ด์๋ ์ฌ์ฉํ ์ ์๋ค.
const str = 'hello';
Array.from(str); // ['h', 'e', 'l', 'l', 'o']
[...str]; // ['h', 'e', 'l', 'l', 'o'] -> ์ ๊ฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค
for of / for in ๋ด๋ถ ๋์์ ์ฐจ์ด์ โญ๏ธ
for of
์ for in
๋ฌธ์ ์ ์ฌํด๋ณด์ด์ง๋ง ๋ด๋ถ๋ ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
for of
for of
๋ฌธ์ ์ดํฐ๋ ์ดํฐ์ next
๋ฉ์๋๋ฅผ ํธ์ถํด์ ์ดํฐ๋ฌ๋ธ(Symbol.iterator
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์๋ ๊ฐ์ฒด)์ ์ํํ๋ค. next
๋ฉ์๋๊ฐ ๋ฐํํ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ value
ํ๋กํผํฐ ๊ฐ์ for of
๋ฌธ์ ๋ณ์์ ํ ๋นํ๋ค. ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ done
์์ฑ์ด false
๋ฉด ๋ฐ๋ณต์ ๊ณ์ํ๊ณ , true
๋ฉด ๋ฐ๋ณต์ ์ค์งํ๋ค.
for (๋ณ์์ ์ธ๋ฌธ of ์ดํฐ๋ฌ๋ธ) {
/* ... */
}
for in
for in
๋ฌธ์ ๊ฐ์ฒด์ ํ๋กํ ํ์
์ฒด์ธ์ ์กด์ฌํ๋ ๋ชจ๋ ํ๋กํ ํ์
์ ํ๋กํผํฐ ์ค์์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ(ํ๋๊ทธ) [[Enumerable]]
๊ฐ์ด true
์ธ ํ๋กํผํฐ๋ฅผ ์ํํ๋ฉฐ ์ด๊ฑฐ(enumeration) ํ๋ค(๊ฐ์ฒด ํ๋กํผํฐ ํน์ ์์๋ฐ์ ํ๋กํ ํ์
์ ํ๋กํผํฐ). ํ๋กํผํฐ ํค๊ฐ ์ฌ๋ฒ์ธ ํ๋กํผํฐ๋ ์ด๊ฑฐํ์ง ์๋๋ค.
for (๋ณ์์ ์ธ๋ฌธ in ๊ฐ์ฒด) {
/* ... */
}
ํ๋กํผํฐ์ ์ด๊ฑฐ ๊ฐ๋ฅ์ฌ๋ถ๋ ํ๋กํผํฐ ์ค๋ช
์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ Object.getOwnPropertyDescriptor
๋ฉ์๋๋ฅผ ์ด์ฉํด ํ์ธํ ์ ์๋ค. ๊ฐ์ฒด ํ๋กํผํฐ ์ค๋ช
์์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ ๋งํฌ ์ฐธ๊ณ .
const obj = { name: 'John' };
Object.getOwnPropertyDescriptor(obj, 'name');
// {value: 'John', writable: true, enumerable: true, configurable: true}
// enumerable ํ๋๊ทธ๊ฐ true์ด๋ฏ๋ก for in ๋ฌธ์ผ๋ก ์ํํ ์ ์๋ ๊ฒ
for in
์ ๊ฐ์ฒด ํ๋กํผํฐ๋ฟ๋ง ์๋๋ผ ์์ ๋ฐ์ ํ๋กํ ํ์
์ ํ๋กํผํฐ๊น์ง ์ด๊ฑฐํ๋ค. ํ์ง๋ง toString
๊ฐ์ Object.prototype
์ ํ๋กํผํฐ๋ [[Enumerable]]
๊ฐ์ด false
์ด๋ฏ๋ก ์ด๊ฑฐ๋์ง ์๋๋ค.
Object.getOwnPropertyDescriptor(Object.prototype, 'toString');
// {writable: true, enumerable: false, configurable: true, value: ƒ}
for (const attr in Object.prototype) console.log(attr); // undefined
Symbol.asyncIterator — ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ
์ง๊ธ๊น์ง ์ดํด๋ณธ ์ดํฐ๋ ์ดํฐ๋ ๋ชจ๋ ๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ค. ๋ง์ฝ ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ฑฐ๋ ๋น๋๊ธฐ ์์ ์ ์ํํด์ผ ํ๋ค๋ฉด ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ฅผ ์ด์ฉํ๋ฉด ๋๋ค. ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ง๋๋ ค๋ฉด ์๋ ์์ ์ด ํ์ํ๋ค.
Symbol.iterator
๋์Symbol.asyncIterator
์ฌ์ฉnext
๋ฉ์๋๋ ํ๋ก๋ฏธ์ค ๋ฐํ- ๋ฐ๋ณต ์์
์
for await (const item of iterable)
์ฌ์ฉ
๋๊ธฐ ์ดํฐ๋ ์ดํฐ | ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ | |
์ดํฐ๋ ์ดํฐ ์ ๊ณต ๋ฉ์๋ | Symbol.iterator |
Symbol.asyncIterator |
next() ๋ฉ์๋ ๋ฐํ ๊ฐ |
๋ชจ๋ ๊ฐ | Promise |
๋ฐ๋ณต ์์ | for of |
for await of |
const range = {
from: 1,
to: 5,
// ๋ฐ๋ณต๋ฌธ ์ต์ด ์คํ ์ Symbol.asyncIterator ํธ์ถ -> ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ
[Symbol.asyncIterator]() {
return {
current: this.from,
last: this.to,
// next ๋ฉ์๋ ์์ async ํค์๋๋ฅผ ๋ถ์์ผ๋ฏ๋ก ํญ์ ํ๋ก๋ฏธ์ค ๋ฐํ
// ๋ฐ๋ณต๋ฌธ์ ์ํด ๊ฐ ์ดํฐ๋ ์ด์
๋ง๋ค next() ํธ์ถ -> ํ๋ก๋ฏธ์ค๋ก ๊ฐ์ผ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด ๋ฐํ
async next() {
await new Promise((resolve) => setTimeout(resolve, 1000)); // ๋น๋๊ธฐ ์์
if (this.current <= this.last) {
return { done: false, value: this.current++ };
}
return { done: true };
},
};
},
};
(async () => {
for await (const value of range) console.log(value);
})(); // 1์ด ๊ฐ๊ฒฉ์ผ๋ก 1~5๊น์ง ์ถ๋ ฅ
๐ก ์ ๊ฐ ๋ฌธ๋ฒ์ ์ผ๋ฐ ์ดํฐ๋ ์ดํฐ(Symbol.iterator
)๊ฐ ํ์ํ๋ฏ๋ก ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์์ ์๋ํ์ง ์๋๋ค.
console.log(...range); // Found non-callable @@iterator
๋ ํผ๋ฐ์ค
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ํ๊ฐ ์์์ ๊ฒฐํฉ์ฑ (1) | 2024.05.03 |
---|---|
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ ๋๋ ์ดํฐ Generator ์ด ์ ๋ฆฌ (0) | 2024.05.03 |
[React] ๋ฆฌ์กํธ ํ์๊ธฐ(TypeWriter) ํจ๊ณผ ๊ตฌํํ๊ธฐ feat.์ ๋๋ ์ดํฐ (0) | 2024.05.03 |
[HTML/CSS] ์์ดํฐ ์ฌํ๋ฆฌ 100vh ์ด์ ํด๊ฒฐ (0) | 2024.05.03 |
[HTML/CSS] ์์ดํฐ ์ฌํ๋ฆฌ ํ ๋ง ์ปฌ๋ฌ ๋ณ๊ฒฝ ๋ฐฉ๋ฒ (0) | 2024.05.03 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ํ๊ฐ ์์์ ๊ฒฐํฉ์ฑ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ํ๊ฐ ์์์ ๊ฒฐํฉ์ฑ
2024.05.03 -
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ ๋๋ ์ดํฐ Generator ์ด ์ ๋ฆฌ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ ๋๋ ์ดํฐ Generator ์ด ์ ๋ฆฌ
2024.05.03 -
[React] ๋ฆฌ์กํธ ํ์๊ธฐ(TypeWriter) ํจ๊ณผ ๊ตฌํํ๊ธฐ feat.์ ๋๋ ์ดํฐ
[React] ๋ฆฌ์กํธ ํ์๊ธฐ(TypeWriter) ํจ๊ณผ ๊ตฌํํ๊ธฐ feat.์ ๋๋ ์ดํฐ
2024.05.03 -
[HTML/CSS] ์์ดํฐ ์ฌํ๋ฆฌ 100vh ์ด์ ํด๊ฒฐ
[HTML/CSS] ์์ดํฐ ์ฌํ๋ฆฌ 100vh ์ด์ ํด๊ฒฐ
2024.05.03