들어가며
JavaScript 에서 Array 가 제공하는 map, filter, reduce 등의 메서드를 직접 구현하는 과정에서 for ... of 문을 공통적으로 사용했다. for ... of 문으로 순회 가능하기 위해서는 반드시 해당 자료구조가 iterable 해야 한다는 것을 알게 되었다. 하지만 iterable 이 무엇이고 어떤 역할을 하는지 알지 못해 이번 시간을 통해 이에 대해 알아보고자 한다.
ko.javascript.info 사이트에서 이에 대해 잘 설명해주고 있어 이 자료를 참고했다.
iterable 객체란?
iterable 객체란 반복 가능한 객체라고 부르기도 하며, for ... of 구문과 함께 ES2015에서 도입되었다.
iterable 객체와 다른 객체와의 가장 큰 차이점은 객체의 Symbol.iterator 속성에 메서드 next 를 가지는 객체를 반환하는 함수가 들어있다는 것이다.
해당 객체는 iterable protocol 을 만족한다고도 말한다.
iterator protocol
앞에서 iterable protocol을 만족하려면, Symbol.iterator 속성에 저장되어 있는 함수는 iterator 객체를 반환해야 한다.
iterator 객체는 다음과 같은 조건을 만족하는 객체이다.
- iterator 객체는 next 라는 메서드를 가진다.
- next 메서드는 다음 두 속성을 가지는 객체를 반환해야 한다.
- done : 반복이 모두 끝났는지를 나타낸다.
- value : 현재 순서의 값을 나타낸다.
위 조건을 iterator protocol 이라고 한다.
Symbol.iterator
객체가 iterable protocol 을 만족하기 위해서는 Symbol.iterator 속성에 iterator 객체를 반환하는 함수가 저장되어 있어야 한다.
또한 iterator protocol 을 만족하기 위해서는 iterator 객체가 next 라는 메서드를 가져야 하며, 이 next 메서드는 done, value 속성을 가지는 객체를 반환해야 한다.
iterable protocol, iterator protocol 을 만족하는 객체를 아래 요구사항에 맞춰 직접 구현해보겠다.
요구사항) range 라는 객체의 from 값부터 to 값까지 for ... of 문으로 순회하여 값을 차례대로 출력해주세요.
let range = {
from: 1,
to: 10
}
구현)
let range = {
from: 1,
to: 10
}
range[Symbol.iterator] = function() {
// iterator 객체
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return { done: false, value: this.current++ }
} else {
return { done: true }
}
}
}
}
for (const num of range) {
console.log(num);
}
실행 결과는 다음과 같다.
요구사항을 충족하여 range 라는 객체의 from 값부터 to 값까지 차례대로 출력했다.
for ... of 문을 호출하는 과정에서 무슨 일이 일어나는지 차례대로 알아보겠다.
1. for ... of 문이 호출되자마자 Symbol.iterator 를 호출한다. Symbol.iterator 는 이터레이터 객체(메서드 next 가 있는 객체)를 반환한다.
2. 이후 for ... of 문은 이터레이터 객체만을 대상으로 동작한다.
3. for ... of 에 다음 값이 필요하면, for ... of 는 이터레이터 객체의 next 메서드를 호출한다.
4. next 메서드의 반환 값은 { done: Boolean, value: any } 형태로 반환한다. done이 true인 경우 반복이 종료되었음을 의미하며, done이 false 인 경우 value 에 다음 값이 저장된다.
iterable 객체의 사용
어떤 객체가 iterable이라면, 그 객체에 대해서 다음과 같은 기능들을 사용할 수 있다.
- for ... of 문
- spread 연산자 (...)
- 분해대입(destructuring assignment)
- iterable 을 인수로 받는 함수
대표적인 내장 이터러블 : 배열과 문자열
배열과 문자열은 대표적인 내장 이터러블이며, 내부적으로 Symbol.iterator 가 구현되어 있다.
배열과 문자열은 앞서 언급된 기능들을 사용할 수 있다.
배열에 대해,
const arr = [1, 2, 3, 4, 5];
// for ... of 문을 통해 순회 가능
for (const el of arr) {
console.log(el);
}
// spread 연산자
const newArr = [...arr, 6];
console.log(newArr);
// 분해대입
const [first, second] = arr;
console.log(first, second);
실행 결과 :
문자열에 대해,
const str = "test";
// for ... of 문을 통해 순회 가능
for (const char of str) {
console.log(char);
}
// spread 연산자
const characters = [...str];
console.log(characters);
// 분해대입
const [c1, c2] = str;
console.log(c1, c2);
// Array.from은 iterable 혹은 array-like 객체를 인수로 받는다.
const characterArr = Array.from(str);
console.log(characterArr);
실행 결과 :
출처
https://ko.javascript.info/iterable
https://helloworldjavascript.net/pages/260-iteration.html#iterator-protocol
'프로그래밍 언어 > JavaScript' 카테고리의 다른 글
[JavaScript] 커링 (0) | 2023.01.12 |
---|---|
[JavaScript] 예시를 통해 알아보는 this (0) | 2022.12.28 |
[JavaScript] 문자열 자르기 (substr, substring, slice) (0) | 2022.12.05 |
JavaScript 의 동작방식 (0) | 2022.11.12 |
[JavaScript] 반복문 (0) | 2022.11.05 |