CH 34. 이터러블
34.1 이터레이션 프로토콜
34.1.1 이터러블
- 이터러블 프로토콜을 준수한 객체
- Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체
- 이터러블은 for ... of 문으로 순회할 수 있으며 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용
const arr = [1, 2, 3];
console.log(Symbol.iterator in arr); // true
// for ... of 문으로 순회 가능
for (const item of arr) {
console.log(item);
}
// 스프레드 사용
console.log([...arr]); // [1, 2, 3]
34.1.2 이터레이터
- 이터레이터 프로토콜을 준수한 객체
- 이터러블의 요소를 탐색하기 위한 포인터 역할
- 이터러블의 Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 가짐
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log('next' in iterator); // true
34.2 빌트인 이터러블
- 표준 빌트인 이터러블


34.3 for ... of 문
- 프로퍼티 어트리뷰트의 값이 참인 프로퍼티를 순회하며 열거함
- 프로퍼티 키가 심벌인 프로퍼티는 열거하지 않음
for (const item of [1, 2, 3]) {
console.log(item); // 1 2 3
}
34.4 이터러블과 유사 배열 객체
- 유사 배열 객체는 이터러블이 아닌 일반 객체
: Symbol.iterator 메서드가 없어 for ... of 문으로 순회할 수 없음

34.5 이터레이션 프로토콜의 필요성
- 이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여
데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록
데이터 소비자와 데이터 공급자를 연결하는 인터페이스의 역할을 함

34.6 사용자 정의 이터러블
34.6.1 사용자 정의 이터러블 구현
- 이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면 사용자 정의 이터러블이 됨
// 피보나치 수열을 구현한 사용자 정의 이터러블
const fibo = {
// Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수
[Symbol.iterator]() {
let [pre, cur] = [0, 1];
const max = 10;
return {
next() {
[pre, cur] = [cur, pre + cur];
return {value:cur, done:cur >= max};
}
};
}
};
for (const num of fibo) {
console.log(num); // 1 2 3 5 8
}
34.6.2 이터러블을 생성하는 함수
- 피보나치 수열의 예에서 수열의 최대값을 외부에서 전달할 수 있도록 수정
- 수열의 최대값을 인수로 전달받아 이터러블을 반환하는 함수를 만들면 됨
// 피보나치 수열을 구현한 사용자 정의 이터러블
// 수열의 최대값을 인수로 전달받는다
const fibo = function (max) {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() {
return {
next() {
[pre, cur] = [cur, pre + cur];
return {value:cur, done:cur >= max};
}
};
}
};
};
for (const num of fibo(10)) {
console.log(num); // 1 2 3 5 8
}
34.6.3 이터러블이면서 이터레이터인 객체를 생성하는 함수
// 이터러블이면서 이터레이터인 객체를 반환하는 함수
const fibo = function (max) {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() {return this;},
next() {
[pre, cur] = [cur, pre + cur];
return {value:cur, done:cur >= max};
}
};
};
// iter는 이터러블이면서 이터레이터
let iter = fibo(10);
// for ... of 문으로 순회할 수 있음
for (const num of fibo(10)) {
console.log(num); // 1 2 3 5 8
}
34.6.4 무한 이터러블과 지연 평가
// 무한 이터러블을 생성하는 함수
const fibo = function () {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() {return this;},
next() {
[pre, cur] = [cur, pre + cur];
return {value:cur};
}
};
};
// for ... of 문으로 순회할 수 있음
for (const num of fibo()) {
if (num > 10000) break;
console.log(num); // 1 2 3 5 8 ... 4181 6765
}
CH 35. 스프레드 문법
- 스프레드 문법의 결과물은 값으로 사용할 수 없고, 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용할 수 있음
1. 함수 호출문의 인수 목록
2. 배열 리터럴의 요소 목록
3. 객체 리터럴의 프로퍼티 목록
35.1 함수 호출문의 인수 목록에서 사용하는 경우
- 문제가 생기는 경우?
: Math.max 메서드에 숫자가 아닌 배열을 인수로 전달하면 최대값을 구할 수 없으므로 NaN 반환
var arr = [1, 2, 3];
// 스프레드 문법을 사용하여 1, 2, 3으로 펼쳐 전달
const max = Math.max(...arr); // 3
35.2 배열 리터럴 내부에서 사용하는 경우
35.2.1 concat
- 2개의 배열을 1개의 배열로 결합하고 싶은 경우
// ES5
var arr = [1, 2].concat([3, 4]);
console.log(arr); // [1, 2, 3, 4]
// ES6
const arr = [...[1, 2], ...[3, 4]];
console.log(arr); // [1, 2, 3, 4]
35.2.2 splice
const arr1 = [1, 4];
const arr2 = {2, 3};
arr1.splice(1, 0, ...arr2);
console.log(arr1); // [1, 2, 3, 4]
35.2.3 배열 복사
- 원본 배열의 각 요소를 얕은 복사하여 새로운 복사본 생성
// ES5
var origin = [1, 2];
var copy = origin.slice();
console.log(copy); // [1, 2]
console.log(copy === origin); // false
// ES6
const origin = [1, 2];
const copy = [...origin];
console.log(copy); // [1, 2]
console.log(copy === origin); // false
35.2.4 이터러블을 배열로 반환
// 방법1
function sum() {
return [...arguments].reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3)); // 6
// 방법2
// Rest파라미터를 사용하는 것
const sum = (...args) => args.reduce((pre, cur) => pre + cur, 0);
console.log(sum(1, 2, 3)); // 6
35.3 객체 리터럴 내부에서 사용하는 경우
// 객체 병합
const merged = { ...{x:1, y:2}, ...{y:10, z:3}};
console.log(merged); // {x:1, y:10, z:3}
// 특정 프로퍼티 변경
const changed = { ...{x:1, y:2}, y:100};
console.log(changed); // {x:1, y:100}
// 프로퍼티 추가
const added = { ...{x:1, y:2}, z:0};
console.log(added); // {x:1, y:2, z:0}
CH 36. 디스트럭처링 할당
36.1 배열 디스트럭처링 할당
- ES6의 배열 디스트럭처링 할당은 배열의 각 요소를 배열로부터 추출해 1개 이상의 변수에 할당함
- 배열 디스트럭처링 할당의 대상은 이터러블이어야 하며, 할당 기준은 배열의 인덱스 (순서)
- 배열 디스트럭처링 할당을 위해서는 할당 연산자 왼쪽에 값을 할당받을 변수를 선언해야 함
- 우변에 이터러블을 할당하지 않으면 에러가 발생
- 배열 디스트럭처링 할당을 위한 변수에 Rest 파라미터와 유사하게 Rest 요소를 사용할 수 있음
- 이때 Rest 요소는 반드시 마지막에 위치해야 함
const arr = [1, 2, 3];
const [one, two, three] = arr;
console.log(one, two, three); // 1 2 3
const [x, ...y] = [1, 2, 3];
console.log(x, y); // 1 [2, 3]
36.2 객체 디스트럭처링 할당
- ES6의 객체 디스트럭처링 할당은 객체의 각 프로퍼티를 객체로부터 추출해 1개 이상의 변수에 할당함
- 할당 기준은 프로퍼티 키 (순서는 의미가 없으며, 프로퍼티 키가 일치하면 할당)
- Rest 프로퍼티 사용 가능 (반드시 마지막에 위치해야 함)
const user = {firstName:'HB', lastName:'Kim'};
const {lastName, firstName} = user;
console.log(firstName, lastName); // HB kim
// Rest 프로퍼티
const {x, ...rest} = {x:1, y:2, z:3};
console.log(x, rest); // 1 {y:2, z:3}
'2022-2 웹개발 스터디' 카테고리의 다른 글
[모던 JS] CH40. 이벤트 (0) | 2022.11.20 |
---|---|
[모던 JS] CH37. Set과 Map, CH42. 비동기 프로그래밍 (1) | 2022.11.20 |
[모던 JS] CH 39. DOM (1) | 2022.11.13 |
[모던 JS] CH 38. 브라우저의 렌더링 과정 (0) | 2022.11.12 |
[모던 JS] CH 32. String, CH33. 7번째 데이터 타입 Symbol (1) | 2022.11.08 |