Iterable & Iterator

For Loop

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 반볡문의 for loop λŠ” λ‹€μŒ λͺ‡κ°€μ§€λ‘œ λ‚˜λ‰œλ‹€.

  • for
    • κ°€μž₯ 기본적인 for loop
  • forEach
    • 배열을 μˆœνšŒν•˜λ©° value 와 index λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•œλ‹€.
    • break, return 으둜 루프λ₯Ό 쀑단할 수 μ—†λ‹€.
  • for in
    • λ°°μ—΄μ˜ 인덱슀만 μˆœν™˜ ν•˜λŠ”κ²ƒμ΄ μ•„λ‹Œ ν”„λ‘œν† νƒ€μž… 체인을 ν¬ν•¨ν•œ λͺ¨λ“  속성을 μˆœνšŒν•œλ‹€.
    • λ°°μ—΄λ³΄λ‹€λŠ” 객체λ₯Ό 순회 ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ 루프이닀.
  • for of
    • for in 으둜 배열을 μˆœνšŒν•  λ•Œ μƒκΈ°λŠ” λ¬Έμ œμ λ“€μ„ ν•΄μ†Œν•˜μ˜€λ‹€.

for of λŠ” μˆœνšŒκ°€λŠ₯ν•œ (iterable) 객체λ₯Ό μƒλŒ€λ‘œ μ‚¬μš© κ°€λŠ₯ ν•˜λ‹€.

μˆœνšŒκ°€λŠ₯ν•œ (Iterable) ν•œ κ°μ²΄λŠ” Symbol.iterator 심볼을 μ†μ„±μœΌλ‘œ 가지고 있으며 μ΄ν„°λ ˆμ΄ν„° 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” 객체 λ₯Ό λœ»ν•œλ‹€.
ν•΄λ‹Ή μŠ€νŒ©μ„ μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œ 이라고 ν•˜λ©° ν•΄λ‹Ή μŠ€νŒ©μ„ κ΅¬ν˜„ν•œ 객체λ₯Ό μ΄ν„°λŸ¬λΈ” 객체 라고 ν•œλ‹€.

Iterable

ECMA6 μ—μ„œ λ„μž…λœ μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œ (Iteration Protocal) 은 데이터 μ»¬λ ‰μ…˜μ„ μˆœνšŒν•˜κΈ° μœ„ν•œ ν”„λ‘œν† μ½œ (κ·œμΉ™) 이닀.

μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œ

이 κ°μ²΄λŠ” for...of 둜 순회 κ°€λŠ₯ν•˜λ©° Spread λ¬Έλ²•μ˜ ν”Όμ—°μ‚°μž (λŒ€μƒ) κ°€ 될 수 μžˆλ‹€.

μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체λ₯Ό μ΄ν„°λŸ¬λΈ” 객체라고 ν•œλ‹€.

즉 λ‹€μ‹œ 말해 μ΄ν„°λŸ¬λΈ”μ€ Symbol.iterator λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ±°λ‚˜ ν”„λ‘œν† νƒ€μž… 체인에 μ˜ν•΄ μƒμ†ν•œ 객체λ₯Ό λ§ν•œλ‹€.

일반적으둜 배열은 Symbol.iterator λ©”μ„œλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€. κ·ΈλŸ¬λ―€λ‘œ μ΄ν„°λŸ¬λΈ”ν•œ 객체이닀.

μ΄ν„°λŸ¬λΈ” = μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체

const array = [1, 2, 3];

// 배열은 Symbol.iterator λ©”μ„œλ“œλ₯Ό μ†Œμœ 
console.log(Symbol.iterator in array);  // true

for (const num of array) {
  console.log(num);
}
const obj = {a: 1, b: 2};

// 일반적인 κ°μ²΄λŠ” Symbol.iterator λ©”μ„œλ“œλ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(Symbol.iterator in obj);  // false

// TypeError: obj is not iterable
// -> obj λŠ” μ΄ν„°λŸ¬λΈ” ν•˜μ§€ μ•Šλ‹€. 즉 μˆœν™˜ κ°€λŠ₯ν•˜μ§€ μ•Šλ‹€.
// -> Symbol.iterator λ©”μ„œλ“œκ°€ μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.
for (const p of obj) {
  console.log(p);
}

Symbol.iterator 의 ν‚€λ₯Ό 가지고 μžˆλŠ” 객체둜써 λ‹€μŒ μŠ€νŽ™μ„ κ΅¬ν˜„ν•œ 객체이닀.

Iterator μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ ν•˜κ³  μžˆλŠ” 객체λ₯Ό Iterable 객체라고 ν•œλ‹€.

  • Symbol.iterator 의 ν‚€λ₯Ό κ°–κ³  μžˆλ‹€.
  • κ°’μœΌλ‘œ 인자λ₯Ό 받지 μ•Šκ³  Iterator Object λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜κ°€ μ˜¨λ‹€.
{
  [Symbol.iterator]: function () {
    return {
      next: function {
        return { value: 1, done: false };
      }
    };
  }
}

Iterator

μ΄ν„°λŸ¬λΈ”κ³Ό λ°€μ ‘ν•œ 관련이 μžˆλŠ” μ΄ν„°λ ˆμ΄ν„°λŠ” μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œ 객체이닀.

μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ€ μ΄ν„°λŸ¬λΈ” 객체가 λ°˜ν™˜ν•˜λŠ” Symbol.iterator λ₯Ό λ§ν•œλ‹€.

이 Symbol.iterator λŠ” λ‹€μŒκ³Ό 같은 νŠΉμ§•μ„ κ°–λŠ”λ‹€.

  • next() λ©”μ„œλ“œλ₯Ό 가지고 μžˆλ‹€.
  • next() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λŸ¬λΈ” 객체λ₯Ό μˆœνšŒν•˜λŠ” ꡬ쑰λ₯Ό 가진닀.
  • μ΄ν„°λŸ¬λΈ” 객체λ₯Ό μˆœνšŒν•˜λ©΄μ„œ value, done ν”„λ‘œνΌν‹°λ₯Ό κ°€μ§€λŠ” 객체λ₯Ό λ°˜ν™˜ν•œλ‹€. (Iterator Result)
const array = [1, 2, 3];

// μ΄ν„°λ ˆμ΄ν„°λ₯Ό λ°˜ν™˜
const iterator = array[Symbol.iterator]();

// next() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν• λ•Œ λ§ˆλ‹€ μ΄ν„°λŸ¬λΈ”μ„ μˆœνšŒν•œλ‹€.
// next() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ value, done ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ” Iterator Result 객체λ₯Ό λ°˜ν™˜
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}

μ΄λŠ” TC39 μ—μ„œ μ •μ˜ν•œ Iterator Interface μ •μ˜λ₯Ό λ”°λ₯Έ Object 둜써 λ‚΄μš©μ€ λ‹€μŒκ³Ό κ°™λ‹€.

  • next λΌλŠ” ν‚€λ₯Ό κ°–κ³  있으며 κ°’μœΌλ‘œ 인자λ₯Ό 받지 μ•Šκ³  Iterator Result Object λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜κ°€ μ˜¨λ‹€.
  • Iterator Result Object λŠ” value 와 done μ΄λΌλŠ” ν‚€λ₯Ό κ°–κ³  μžˆλ‹€.
    • value λŠ” μ‹€μ œ 값을 의미
    • done λŠ” 계속 반볡 ν•  수 μžˆλŠ”μ§€ λ”°λ₯Έ boolean κ°’

μ˜μ›νžˆ 0 을 λ°˜ν™˜ν•˜λŠ” Iterator

{
  next: function () {
    return {
      value: 0,
      done: false
    };
  }
}

각 배열을 μˆœνšŒν•˜λ©° λ°°μ—΄μ˜ 끝 값을 λ°˜ν™˜ν•˜λŠ” Iterator

{
  data: [1, 2, 3, 4]
  next: function () {
    return {
      done: this.data.length === 0,
      value: this.data.pop()
    };
  }
}

ECMA6 μ—μ„œλŠ” 객체 λ¦¬ν„°λŸ΄ μž‘μ„± μˆœμ„œμ— 따라 νŒŒμ‹± ν•œλ‹€.

예λ₯Ό λ“€λ©΄ μœ„ μ½”λ“œμ˜ done κ³Ό value μ€‘μ—μ„œ done 이 λ¨Όμ € μž‘μ„±λ˜μ–΄ 있기 λ•Œλ¬Έμ— done 을 λ¨Όμ € νŒŒμ‹±ν•œλ‹€.
ECMA5 μ—μ„œλŠ” done 이든 value λ“  μ–΄λŠκ²ƒμ„ λ¨Όμ € νŒŒμ‹±ν• μ§€ 보μž₯이 μ•ˆλ¨

μš”μ•½

  • μ΄ν„°λŸ¬λΈ” ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ -> μ΄ν„°λŸ¬λΈ” 객체
    • Symbol.iterator λ©”μ„œλ“œλ₯Ό μ†Œμœ ν•œ 객체
    • ν˜Ήμ€ ν”„λ‘œν† νƒ€μž… 체인에 μƒμ†ν•œ 객체
  • μ΄ν„°λ ˆμ΄ν„° ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ -> μ΄ν„°λ ˆμ΄ν„° 객체
    • Symbol.iterator λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œ 객체
    • next() λ©”μ„œλ“œλ₯Ό 가지고 있고 next() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λŸ¬λΈ”μ„ μˆœνšŒν•˜λ©° value, done ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ” κ²°κ³Ό 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” λ™μž‘κ΅¬μ‘°λ₯Ό κ°€μ§€λŠ” 객체