회고록 블로그
[공부 필기] JavaScript 문법 공부 26일차 (2) 본문
※ 필자는 초초초보자입니다.
※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.
공부하고 있는 자료 : modern JavaScript tutorial
https://ko.javascript.info/iterable
✅ iterable 객체
- 반복 가능한 객체 : iterable 객체
- 배열을 일반화한 객체이다.
► iterable 객체의 대표적인 예가 [배열], [문자열]이다.
- 이 이터러블 이라는 개념을 사용하면 for...of 반복문을 적용할 수 있다.
- 이터러블을 배우는 이유는
배열이 아닌 객체라도 어떤 것들의 컬렉션(목록, 집합 등)을 나타내고 있는 경우
for...of문을 적용할 수 있으면 컬렉션을 순회하는데 편하기 때문이다.
/* 배열이 아니더라도 for...of가 적용될 수 있도록 해보는게 목표 */
✅ Symbol.iterator
- 이터러블 객체를 직접 만들어보자
- 여기 for...of문을 적용하기에 적합해 보이는 배열이 아닌 객체가 있다.
let range = {
from: 1,
to: 5
};
- range를 이터러블로 만들려면(=for...of가 동작하도록 하려면)
객체에 Symbol.iterator라는 특수 내장 심볼의 메서드를 추가해야한다.
- for...of가 시작되자마자 Symbol.iterator를 호출하는데 (없으면 에러 발생) 이 Symbol.iterator에는 다음과 같은 작업이 구현되어야 한다.
1) Symbol.iterator는 반드시 이터레이터(=next라는 메서드가 있는 객체이다)를 반환해야한다.
2) 이후 for...of는 반환된 객체(이터레이터)만을 대상으로 동작한다.
3) for...of에 다음 값이 필요하면, for...of는 이터레이터의 next() 메서드를 호출한다.
4) next() 메서드의 반환 값은 {done: Boolean, value: any}와 같은 형태이어야 한다.
5) done=true는 반복이 종료됐음을 의미한다.
6) done=false일 땐, value에 다음 값이 저장된다.
- 그래서 코드로 구현해보면 다음과 같다!
let range = {
from: 1,
to: 5
};
range[Symbol.iterator] = function() {
// 1. Symbol.iterator는 반드시 이터레이터(=next라는 메서드가 있는 객체이다)를 반환해야한다.
return {
current: this.from,
last: this.to,
// next() 메서드의 반환 값은 {done: Boolean, value: any}와 같은 형태이어야 한다.
next() {
if (this.current <= this.last)
return {done: false, value: this.current++ }; // done=false일 땐, value에 다음 값이 저장된다.
else
return { done: true }; // done=true는 반복이 종료됐음을 의미한다.
},
};
};
//0. for...of가 시작되자마자 Symbol.iterator를 호출한다.
for (let num of range) {
console.log(num);
}
- 이터러블 객체의 핵심은 [관심사의 분리(SoC)] 라고 한다.
► range 객체에는 next() 메서드가 없다.
► 대신 range[Symbol.interator]()를 호출해서 만든 '이터레이터' 객체와 이 객체의 메서드 next()에서 반복에 사용될 값을 만들어낸다.
- 이렇게하면 이터레이터 객체와 반복 대상인 객체를 분리할 수 있다.
► 물론 분리하지 않고 합쳐서, range 자체를 이터레이터로 만들 수도 있다.
- 단점은 for...of 반복문을 하나의 객체에 동시에 사용할 수 없다.
► 이터레이터(객체 자신)가 하나뿐이라 두 반복문이 반복 상태를 공유하기 때문
✅ 문자열은 iterable
- 배열 뿐만 아니라 문자열도 이터러블이다.
let str = "✅‣";
for (let char of str) {
console.log(char);
}
✅ iterator를 명시적으로 호출하기
- 직접 이터레이터를 호출해서 순회를 해보자.
► done과 value를 이용해서 수동으로 값을 가져온다.
► 이렇게 사용하면 반복을 시작했다가 잠시 멈춰 다른 작업을 하다가 다시 반복을 시작하는 등 반복 작업을 쪼갤 수 있다.
let str = "✅✅✅✅";
let iterator = str[Symbol.iterator]();
console.log(iterator); // Object [String Iterator] {}
while (1) {
let char = iterator.next();
if (char.done) break ;
console.log(char.value); // 한글자씩 출력
}
✅ 이터러블과 유사 배열
- 이터러블 vs 유사배열
► 이터러블(iterable) : Symbol.iterator 메서드가 구현된 객체이다.
► 유사배열 : 인덱스, length 프로퍼티가 있어서 배열처럼 보이는 객체이다.
- 브라우저 등 호스트 환경에서 이터러블 객체, 유사배열 객체, 이터러블 객체+유사배열 객체에 다 해당하는 객체를 만날 수 있다.
► 이터러블 객체+유사배열 객체에 다 해당하는 객체의 예
→ for...of를 사용할 수 있으면서 length 프로퍼티/숫자 인덱스가 있는 [문자열]
- 이터러블, 유사 배열은 대개 배열이 아니기 때문에 push, pop 등 메서드를 지원하지 않는다.
► 그렇다면 이터러블, 유사 배열에서 push, pop과 같은 메서드를 적용할 수 있을까..?
✅ Array.from
- 범용 메서드인 Array.from
- 이터러블이나 유사 배열을 받아 진짜 Array를 만들어준다.
► 이 과정을 거치면 이터러블이나 유사 배열에 배열 메서드를 사용할 수 있다.
// 유사배열
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike);
console.log(arrayLike); //{ '0': 'Hello', '1': 'World', length: 2 }
console.log(arr); // [ 'Hello', 'World' ]
console.log(arr.pop()); //World
- Array.from은 객체를 받아 이터러블이나 유사 배열인지 조사를 한다.
► 이터러블 혹은 유사 배열이면, 새로운 배열을 만들고 객체의 모든 요소를 새로운 배열에 복사한다.
- Array.from 메서드는 다음과 같은 인자를 전달한다.
Array.from(obj[, mapFn, thisArg])
- 여기에서 mapFn(매핑 함수)와 thisArg는 선택 사항이다.
► mapFn을 전달하면, 첫번째 인자로 전달한 객체(이터러블 or 유사 배열)의 요소를 추가하기 전에 각 요소를 대상으로 mapFn을 적용한다.
► 즉, 새로운 배열의 요소는 mapFn을 적용한 값이 되는 것이다.
- Array.from을 이용하면 문자열을 배열로 만들 수도 있다.
'2. 프로그래밍 언어 공부 > JavaScript' 카테고리의 다른 글
V8 엔진의 히든 클래스 (0) | 2022.06.12 |
---|---|
JavaScript 문법 :three dots 공부 (0) | 2022.05.30 |
[공부 필기] JavaScript 문법 공부 26일차 (1) (0) | 2022.05.27 |
[공부 필기] JavaScript 문법 공부 25일차 (2) (0) | 2022.05.26 |
[공부 필기] JavaScript 문법 공부 25일차 (1) (0) | 2022.05.26 |