β­• 34.1 μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œ

ES6μ—μ„œ λ„μž…λœ μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ€ 순회 κ°€λŠ₯ν•œ 데이터 μ»¬λ ‰μ…˜(자료ꡬ쑰)λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ ECMAScript 사양에 μ •μ˜ν•˜μ—¬ 미리 μ•½μ†ν•œ κ·œμΉ™μ΄λ‹€.

μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ—λŠ” μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œκ³Ό μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ΄ μžˆλ‹€.

  • μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œ(iterable protocol) Well-known Symbol인 Symbol.iteratorλ₯Ό ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•œ λ©”μ„œλ“œλ₯Ό 직접 κ΅¬ν˜„ν•˜κ±°λ‚˜ ν”„λ‘œν† νƒ€μž… 체인을 톡해 상속받은 Symbol.iterator λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ μ΄ν„°λ ˆμ΄ν„°λ₯Ό λ°˜ν™˜ν•œλ‹€. μ΄λŸ¬ν•œ κ·œμ•½μ„ μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œμ΄λΌ ν•˜λ©°,Β μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체λ₯Ό μ΄ν„°λŸ¬λΈ”μ΄λΌ ν•œλ‹€. μ΄ν„°λŸ¬λΈ”μ€ for ... of 문으둜 μˆœνšŒν•  수 있으며 μŠ€ν”„λ ˆλ“œ 문법과 λ°°μ—΄ λ””μŠ€νŠΈλŸ­μ²˜λ§ ν• λ‹Ήμ˜ λŒ€μƒμœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.
  • μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œ(iterator protocol) μ΄ν„°λŸ¬λΈ”μ˜ Symbol.iterator λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œΒ μ΄ν„°λ ˆμ΄ν„°
    λ₯Ό λ°˜ν™˜ν•œλ‹€. μ΄ν„°λ ˆμ΄ν„°λŠ” next λ©”μ„œλ“œλ₯Ό μ†Œμœ ν•˜λ©° next λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λŸ¬λΈ”μ„ μˆœνšŒν•˜λ©° value와 done ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ”Β μ΄ν„°λ ˆμ΄ν„° 리절트 객체λ₯Ό λ°˜ν™˜ν•œλ‹€. μ΄λŸ¬ν•œ κ·œμ•½μ„ μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ΄λΌ ν•˜λ©°,Β μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체λ₯Ό μ΄ν„°λ ˆμ΄ν„°λΌ ν•œλ‹€. μ΄ν„°λ ˆμ΄ν„°λŠ” μ΄ν„°λŸ¬λΈ”μ˜ μš”μ†Œλ₯Ό νƒμƒ‰ν•˜κΈ° μœ„ν•œ 포인터 역할을 ν•œλ‹€.

βœ” 34.1.1 μ΄ν„°λŸ¬λΈ”

μ΄ν„°λŸ¬λΈ”μ€ 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

βœ” 34.1.2 μ΄ν„°λ ˆμ΄λΈ”

μ΄ν„°λŸ¬λΈ”μ˜ 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 ν”„λ‘œνΌν‹°λŠ” μ΄ν„°λŸ¬λΈ”μ˜ 순회 μ™„λ£Œ μ—¬λΆ€λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

β­• 34.2 빌트인 μ΄ν„°λŸ¬λΈ”

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체인 빌트인 μ΄ν„°λŸ¬λΈ”μ„ μ œκ³΅ν•œλ‹€. λ‹€μŒμ˜ ν‘œμ€€ 빌트인 객체듀은 빌트인 μ΄ν„°λŸ¬λΈ”μ΄λ‹€.


β­• 34.3 for … of λ¬Έ

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
}

β­• 34.4 μ΄ν„°λŸ¬λΈ”κ³Ό μœ μ‚¬ λ°°μ—΄ 객체

μœ μ‚¬ λ°°μ—΄ κ°μ²΄λŠ” 마치 λ°°μ—΄μ²˜λŸΌ 인덱슀둜 ν”„λ‘œνΌν‹° 값에 μ ‘κ·Όν•  수 있고 length ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ” 객체λ₯Ό λ§ν•œλ‹€. μœ μ‚¬ λ°°μ—΄ κ°μ²΄λŠ” μ΄ν„°λŸ¬λΈ”μ΄ μ•„λ‹Œ 일반 객체닀. λ”°λΌμ„œ Symbol.iterator λ©”μ„œλ“œκ°€ μ—†κΈ° λ•Œλ¬Έμ— for … of 문으둜 μˆœνšŒν•  수 μ—†λ‹€.

단, ES6μ—μ„œ μ΄ν„°λŸ¬λΈ”μ΄ λ„μž…λ˜λ©΄μ„œ μœ μ‚¬ λ°°μ—΄ 객체인 arguments, NodeList, HTMLCollectionκ³Ό 배열에 Symbol.iterator λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•΄ μ΄ν„°λŸ¬λΈ”μ΄ λ˜μ—ˆλ‹€.

β­• 34.5 μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ˜ ν•„μš”μ„±

ES6 μ΄μ „μ˜ 순회 κ°€λŠ₯ν•œ 데이터 μ»¬λ ‰μ…˜(λ°°μ—΄, λ¬Έμžμ—΄, μœ μ‚¬ λ°°μ—΄ 객체, DOM μ»¬λ ‰μ…˜ λ“±)은 ν†΅μΌλœ κ·œμ•½ 없이 각자 λ‚˜λ¦„μ˜ ꡬ쑰λ₯Ό 가지고 forλ¬Έ, for…inλ¬Έ, forEach λ©”μ„œλ“œλ“£ μ•‹μ–‘ν•œ λ°©λ²•μœΌλ‘œ μˆœνšŒν•  수 μžˆμ—ˆλ‹€. ES6 μ—μ„œλŠ” 순회 κ°€λŠ₯ν•œ 데이터 μ»¬λ ‰μ…˜μ„ μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” β€œμ΄ν„°λŸ¬λΈ”β€λ‘œ ν†΅μΌν•˜μ—¬ for…ofλ¬Έ, μŠ€ν”„λ ˆλ“œ 문법, λ°°μ—΄ λ””μŠ€νŠΈλŸ­μ²˜λ§ ν• λ‹Ήμ˜ λŒ€μƒμœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ 일원화 ν–ˆλ‹€.

이처럼 μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ€ λ‹€μ–‘ν•œ 데이터 κ³΅κΈ‰μžκ°€ ν•˜λ‚˜μ˜ 순회 방식을 갖도둝 κ·œμ •ν•˜μ—¬ 데이터 μ†ŒλΉ„μžκ°€ 효율적으둜 λ‹€μ–‘ν•œ 데이터 κ³΅κΈ‰μžλ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ 데이터 μ†ŒλΉ„μžμ™€ 데이터 κ³΅κΈ‰μžλ₯Ό μ—°κ²°ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ˜ 역할을 ν•œλ‹€.


β­• 34.6 μ‚¬μš©μž μ •μ˜ μ΄ν„°λŸ¬λΈ”

βœ” 34.6.1 μ‚¬μš©μž μ •μ˜ μ΄ν„°λŸ¬λΈ” κ΅¬ν˜„

μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜μ§€ μ•ŠλŠ” 일반 객체도 μ΄λŸ¬ν…Œμ΄μ…˜ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λ„λ‘ κ΅¬ν˜„ν•˜λ©΄ μ‚¬μš©μž μ •μ˜μ˜ μ΄ν„°λŸ¬λΈ”μ΄ λœλ‹€.

// ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ΅¬ν˜„ν•œ μ‚¬μš©μž μ •μ˜ μ΄ν„°λŸ¬λΈ”
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κ°€ 되면 λ°˜λ³΅μ„ μ€‘μ§€ν•œλ‹€.

βœ” 34.6.2 μ΄ν„°λŸ¬λΈ”μ„ μƒμ„±ν•˜λŠ” ν•¨μˆ˜

μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ 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
}

βœ” 34.6.3 μ΄ν„°λŸ¬λΈ”μ΄λ©΄μ„œ μ΄ν„°λ ˆμ΄ν„°μΈ 객체λ₯Ό μƒμ„±ν•˜λŠ” ν•¨μˆ˜

μ΄ν„°λŸ¬λΈ”μ΄λ©΄μ„œ μ΄ν„°λ ˆμ΄ν„°μΈ 객체λ₯Ό μƒμ„±ν•˜λ©΄ 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 }

βœ” 34.6.4 λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”κ³Ό 지연 평가

λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”μ„ μƒμ„±ν•˜λŠ” ν•¨μˆ˜λŠ” λ¬΄ν•œ μˆ˜μ—΄μ„ κ°„λ‹¨νžˆ κ΅¬ν˜„ν•  수 μžˆλ‹€.

// λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”μ„ μƒμ„±ν•˜λŠ” ν•¨μˆ˜
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

μœ„ 예제의 μ΄ν„°λŸ¬λΈ”μ€ 지연 평가λ₯Ό 톡해 데이터λ₯Ό μƒμ„±ν•œλ‹€. 지연 ν‰κ°€λŠ” 데이터가 ν•„μš”ν•œ μ‹œμ  μ΄μ „κΉŒμ§€λŠ” 미리 데이터λ₯Ό μƒμ„±ν•˜μ§€ μ•Šλ‹€κ°€ 데이터가 ν•„μš”ν•œ μ‹œμ μ΄ 되면 κ·Έλ•Œμ•Ό λΉ„λ‘œμ†Œ 데이터λ₯Ό μƒμ„±ν•˜λŠ” 기법이닀. 즉, 평가 κ²°κ³Όκ°€ ν•„μš”ν•  λ•ŒκΉŒμ§€ 평가λ₯Ό λŠ¦μΆ”λŠ” 기법이 지연 평가닀.

Ref
https://sosocodingday.tistory.com/203

profile
μ΄μ‚¬μ€‘μž…λ‹ˆλ‹€!🌟https://velog.io/@devkyoung2

0개의 λŒ“κΈ€

κ΄€λ ¨ μ±„μš© 정보