Iterator&Generator - ChoDragon9/posts GitHub Wiki
Iterator
๋ด๋ถ ํํ๋ถ๋ฅผ ๋ ธ์ถํ์ง ์๊ณ ์ด๋ค ๊ฐ์ฒด ์งํฉ์ ์ํ ์์๋ค์ ์์ฐจ์ ์ผ๋ก ์ ๊ทผํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ํจํด์ด๋ค.
Iterable Protocol
์์ฐจ์ ์ผ๋ก ์ ๊ทผํ ์ ์๋ Iterator๋ฅผ ์ ๊ทผํ๊ธฐ ์ํ ํ๋กํ ์ฝ
Java์์ Iterator๋ฅผ ๊ตฌํํ ๋๋ hasNext/next ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ง๋ง Javascript์์๋ next๋ง ์ฌ์ฉ๋๋ค.
์ฃต๋ฃ๋ ๊ฒ์ done property๊ฐ true์ผ ๋๋ก ํ์ธ ๊ฐ๋ฅํ๋ค.
const str = "hi"
const iterator = str[Symbol.iterator]()
console.log(iterator.next()) //{ value: 'h', done: false }
console.log(iterator.next()) //{ value: 'i', done: false }
console.log(iterator.next()) //{ value: undefined, done: true }
Iterator Protocol
๋ฐ์ดํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ๊ทผํ ๋ ์คํ๋๋ ํ๋กํ ์ฝ
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){ //next ๋ฉ์๋๋ฅผ ๊ฐ์ ธ์ผ ํจ
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
//done : iterator์ ๋ฐ๋ณต ์์
์ข
๋ฃ ์ ๋ฌด. boolean ์ฌ์ฉ
//value : iterator๋ก ๋ถํฐ ๋ฐํ๋๋ ๊ฐ, done์ด true์ผ ๋ ์๋ต ๊ฐ๋ฅ
}
};
}
var it = makeIterator(['yo', 'ya']);
console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done); // true
Customize Iterables
Object๋ Iterable ํ์ง ์์ง๋ง Iterator/Iterable Protocol๋ฅผ ํตํด Iterable ํ๊ฒ ๋ง๋ค ์ ์๋ค.
const obj = {
name: 'Smith',
age: 20,
weight: 60
}
console.log([...obj]) //TypeError
obj[Symbol.iterator] = () => {
const arr = Object.keys(obj)
return {
next () {
return arr.length > 0 ?
{ value: obj[arr.pop()], done: false } :
{ done: true }
}
}
}
console.log([...obj]) // [60, 20, 'Smith']
Using Generator
const obj = {
name: 'Smith',
age: 20,
weight: 60
}
obj[Symbol.iterator] = function* () {
const arr = Object.keys(obj)
yield obj[arr.pop()]
yield obj[arr.pop()]
yield obj[arr.pop()]
}
console.log([...obj]) // [60, 20, 'Smith']
Iterable data sources
Arrays, Maps, DOM queies, Strings, Sets, Arguments
Generator
yield
๋ก Iterator
๋ฅผ ์ฝ๊ฒ ์ ์ํ์ฌ Iterable
๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์์. ์ฝ๋ฃจํด
์ ์ง์ํจ.
function*
ํจ์ ์คํ ์ Generator Object
๋ฅผ ๋ฐํํ๋ค. Generator Object
์ ์ธํฐํ์ด์ค๋ next
, return
, throw
๊ฐ ์๋ค.
next
๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด yield
์ ๊ฐ์ด ๋ฐํ๋๋ฉฐ, yield
๋ Generator
๋ฅผ ์ผ์์ ์ง ์ํจ๋ค.
function* genFour () {
yield 1
yield 2
yield 3
return 4
}
let four = getFour()
Generators are both an iterator and an iterable.
four.next() // Object { value: 1, done: false)
four.next() // Object { value: 2, done: false)
four.next() // Object { value: 3, done: false)
four.next() // Object { value: 4, done: true)
[....getFour()] // Array [1, 2, 3, 4]
yield* yields every yield inside a called generator
function* flatten(arr){
for (let x of arr) {
if (x instanceof Array){
yield* flatten(x)
} else {
yield x
}
}
}
let t = flatten([1, 2, [3, 4]])
cursor ์์
const log = txt => {
console.log(`[cursor] ${txt}`)
}
function* getFour () {
log(`getFour: 1`)
yield 1
log(`getFour: 2`)
yield 2
log(`getFour: 3`)
yield 3
log(`getFour: 4`)
yield 4
}
for (const num of getFour()) {
log(`num: ${num}`)
}
// "[cursor] getFour: 1"
// "[cursor] num: 1"
// "[cursor] getFour: 2"
// "[cursor] num: 2"
// "[cursor] getFour: 3"
// "[cursor] num: 3"
// "[cursor] getFour: 4"
// "[cursor] num: 4"