티스토리 뷰

반응형

[챗지피티와 공부를 해보자] 이터러블(iterable)과 이터레이터(iterator)

이터러블, 이터레이터

 

 

 

이터러블(Iterable)

반복가능(=순회할 수 있는) 객체를 말한다.  (배열(Array), 문자열(String), Set, Map, arguments, NodeList)

Symbol.iterator 메서드를 구현하면 해당 객체가 이터러블(iterable)로 동작할 수 있다.

Symbol.iterator가 이터러블 프로토콜을 따르도록 객체를 만드는 메서드이며, 객체에 Symbol.iterator를 구현하면 해당 객체는 이터러블이 된다.

 

특징

  • 이터러블 순회  - for...of  루프 사용 가능
  • 이터러블을 개별 요소로 분해  - spread 연산자 (...) 사용 가능
  • 이터러블을 배열로 변환 -  Array.from() 사용가능
const arr = [1, 2, 3]; 

console.log([...arr]); // [1, 2, 3] 
console.log(Array.from(arr)); // [1, 2, 3] 

for (const num of arr) { 
    console.log(num); // 1 // 2 // 3
}

 

 

 

이터레이터(Iterator)

이터러블을 순차적으로 순회하는 반복자 객체 

이터레이터 객체는 .next() 메서드를 가지고 있으며 호출할때마다 { value, done } 형태의 결과를 반환

 

특징

  • .next() 메서드를 호출하면 { value, done } 객체를 반환
  • done: true가 되면 반복 종료
const arr = [10, 20, 30]; 
const iterator = arr[Symbol.iterator](); 

console.log(iterator.next()); // { value: 10, done: false } 
console.log(iterator.next()); // { value: 20, done: false } 
console.log(iterator.next()); // { value: 30, done: false } 
console.log(iterator.next()); // { value: undefined, done: true } (true 반복 끝)

 

배열같은 기본 객체가 아니어도 이터러블을 구현할 수 있다. 

const customIterable = { 
    data: [100, 200, 300], 
    [Symbol.iterator]() { 
        let index = 0;
        return { 
            next: () => { 
                if (index < this.data.length) { 
                    return { 
                        value: this.data[index++], 
                        done: false 
                    }; 
                } else { 
                    return { 
                        value: undefined, 
                        done: true 
                    }; 
                } 
            } 
        }; 
    } 
}; 

const iterator = customIterable[Symbol.iterator](); 

console.log(iterator.next()); // { value: 100, done: false } 
console.log(iterator.next()); // { value: 200, done: false } 
console.log(iterator.next()); // { value: 300, done: false } 
console.log(iterator.next()); // { value: undefined, done: true }

 

객체에 Symbol.iterator 메서드를 만들고 그 안에서 next 메서드를 리턴하는 형식으로 구현할 수 있다.

이렇게 구현하면 Symbol.iterator가 필요한 for...of 루프에서도 사용 가능하다.

 
 

제네레이터(Generator)

제네레이터를 사용하면 이터레이터를 더 쉽게 구현할 수 있다.
(제네레이터는 따로 학습)
yield를 사용하여 자동으로 이터레이터를 반환하는 함수를 만들 수 있다.

function* generatorFunc() { 
    yield 1; 
    yield 2; 
    yield 3; 
} 

const generator = generatorFunc(); 

console.log(generator.next()); // { value: 1, done: false } 
console.log(generator.next()); // { value: 2, done: false } 
console.log(generator.next()); // { value: 3, done: false } 
console.log(generator.next()); // { value: undefined, done: true }
 

 

자 그렇다면 이터러블과 이터레이터를 요약해보자.

이터러블은 Symbol.iterator 메서드를 구현한 객체이며, for...of 루프나 spread 연산자등을 사용할 수 있고 반환하는 값으로 이터레이터 객체를 반환한다.

(이터러블로 이터레이터 객체 생성, 위에서 언급했듯 제네레이터로도 이터레이터 객체 생성 가능!)

그렇다면 이터레이터는 .next() 메서드를 통해 값을 반환하는 객체로 .next()를 호출하여 사용하고 반환하는 값은 { value, done } 형태의 객체이다.

 

 

질문

Q. 배열과 유사배열 이터러블 이터레이터 간의 유사성 알려줘

 

A. 자바스크립트에서 배열(Array), 유사 배열(Array-like), 이터러블(Iterable), 이터레이터(Iterator)는 서로 관련 있지만, 개념적으로 차이가 있다.

 

배열

- 이터러블이므로 이터레이터를 가질 수 있다.

- 가장 일반적인 순차적 데이터 구조로 Array 객체의 인스턴스이며 다양한 배열의 메서드를 제공한다.

- 특징으로는 Array 프로토타입을 상속받고, 배열 메서드를 사용할 수 있다. length 프로퍼티가 있으며, 이터러블이므로 for...of 루프나 spread 연산자, Array.from()을 사용할 수 있다.

 

유사배열

- 유사배열은 이터러블객체가 아니므로 이터러블이 되려면 Symbol.iterator를 추가해야한다.

- 배열 처럼 length 프로퍼티와 index를 가지지만, 배열의 메서드는 제공하지 않는 객체

- 특징으로는 length 프로퍼티를 가지며 index로 요소 접근 가능하다. 하지만 Array의 프로토타입 메서드는 없다. 하지만 Array.from()을 사용하면 배열로 변환 가능하다.

const arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 }; 

console.log(arrayLike.length); // 3 
console.log(arrayLike[1]); // "b" 

// 배열 메서드는 사용 불가 
// console.log(arrayLike.map(x => x.toUpperCase())); // ❌ TypeError! 

// 배열로 변환 가능 
const realArray = Array.from(arrayLike); 
console.log(realArray.map(x => x.toUpperCase())); // ["A", "B", "C"]

 

- 대표적인 유사배열 객체는 arguments (함수 내부의 매개변수 목록), NodeList (DOM 요소 리스트), HTMLCollection (HTML 요소 집합)이 있다. (Array.from()을 사용하여 배열처럼 활용할 수 있다)

function test() {   
    console.log(arguments.length); // 유사 배열 
    console.log(arguments[0]); // 첫 번째 매개변수 
    console.log(Array.from(arguments).map(x => x * 2)); // 배열로 변환 후 map 사용 가능 
} 

test(1, 2, 3); // 3 // 1 // [2, 4, 6]

 

비교

  length 있음 Array 메서드 사용  가능 for...of 사용 가능 Symbol.iterator 존재 .next() 직접 호출
배열(Array)
유사 배열(Array-like)
이터러블(Iterable) ❌ (필수 아님)
이터레이터(Iterator)

 

Q. 그럼 이터레이터와 이터러블의 관계성은 뭐야??

A. 이터러블(Iterable)과 이터레이터(Iterator)는 반복과 관련된 개념이지만, 서로 다른 역할을 담당한다.

  • 이터러블(Iterable): Symbol.iterator 메서드를 구현한 객체
  • 이터레이터(Iterator): .next() 메서드를 통해 값을 하나씩 반환하는 객체

즉, 이터러블은 이터레이터를 생성할 수 있는 객체이고, 이터레이터는 실제 반복을 수행하는 객체다.

이터레이터는 한번만 사용할 수 있지만(1회성), 이터러블은 새로운 이터레이터를 반환할 수 있기 때문에 여러번 사용할 수 있다.(Symbol.iterator() 호출할때마다 새로운 이터레이터 생성)

const iterator = iterableObj[Symbol.iterator](); 

console.log(iterator.next()); // { value: 0, done: false } 
console.log(iterator.next()); // { value: 1, done: false } 
console.log(iterator.next()); // { value: 2, done: false } 
console.log(iterator.next()); // { done: true } 

const newIterator = iterableObj[Symbol.iterator](); // 새로운 이터레이터 생성 

console.log(newIterator.next()); // { value: 0, done: false }

 

 

Q. 근데 이터러블은 Symbol.iterator를 구현한 객체라고했는데, 이때 배열도 이터러블이라고 한다면 배열도 사실은 객체이기 때문이지?
A. 배열도 사실 객체(Object)이기 때문에 맞다.
자바스크립트에서 모든 배열은 객체(Object)이며 Array는 Object를 상속받는 객체이다. 따라서 typeof 연산자로 확인해보면 'object' 결과가 나온다. 
그리고 객체(Object)를 상속받은 배열(Array)이 이터러블인 이유는 내부적으로 Symbol.iteragor 메서드를 별도로 구현하고 있기 때문이다. (일반 객체는 이터러블이 아님)

const arr = [10, 20, 30]; 

console.log(typeof arr[Symbol.iterator]); // "function" (배열이 `Symbol.iterator`를 가지고 있음)

 

배열의 Symbol.iterator는 함수이므로, 호출하면 이터레이터(Iterator)를 반환한다.

배열의 Symbol.iterator를 호출하면, 이터레이터 객체가 생성되고, .next() 메서드를 통해 값을 하나씩 반환할 수 있다.
const arr = [10, 20, 30]; 

const iterator = arr[Symbol.iterator](); // 배열의 이터레이터 생성 

console.log(iterator.next()); // { value: 10, done: false } 
console.log(iterator.next()); // { value: 20, done: false } 
console.log(iterator.next()); // { value: 30, done: false } 
console.log(iterator.next()); // { value: undefined, done: true } (반복 끝)
 

 

Q. 그럼 배열은, Array를 자바스크립트가 구현할때 Symbol.iterator를 구현했겠네? 로직상

A. 자바스크립트가 Array를 구현할 때, 내부적으로 Symbol.iterator를 직접 구현해서 배열이 기본적으로 이터러블(Iterable) 하도록 만든다.

 

 

Q.구조분해할당할때, 변수에 담을때 스프레드 연산을 통해 나머지변수를 담잖아?

예를들어 const [a, ...rest] = [1,2,3,4] 이런식으로, 이때 구조분해할당 문법에서 ...rest하는 과정에서 이터러블로 만들어서 배열로 만드는거야? 동작 좀 자세히 알려줘

 

A. 구조 분해 할당에서 ...rest(나머지 매개변수)는 내부적으로 이터러블을 순회(iteration)하여 남은 요소들을 새로운 배열로 만들게 되는데 const [a, ...rest] = [1, 2, 3, 4] 같은 코드에서 ...rest는 이터러블을 순회하여 남은 값을 배열로 변환하는 과정이 포함되어 있다.

즉, ...rest는 내부적으로 Symbol.iterator를 호출하여, 이터러블 객체를 순회하며 새로운 배열을 생성하는 것과 동일한 동작을 한다.

 

 

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함