diff --git "a/09\355\232\214\354\260\250(34\354\236\245~37\354\236\245)/\355\231\251\352\267\234\353\217\204.md" "b/09\355\232\214\354\260\250(34\354\236\245~37\354\236\245)/\355\231\251\352\267\234\353\217\204.md" new file mode 100644 index 0000000..f31f18e --- /dev/null +++ "b/09\355\232\214\354\260\250(34\354\236\245~37\354\236\245)/\355\231\251\352\267\234\353\217\204.md" @@ -0,0 +1,368 @@ + +# 34장: 이터러블 +## 34.1 이터레이션 프로토콜 +> ES6에서 도입된 프로토콜로, 순회 가능한 데이터 컬랙션을 만들기 위해 정의된 규칙이다. + +- ES6 이전에는 데이터 컬랙션마다 서로 다른 순회 방법을 제공했다. +- ES6 이후, 이터레이션 프로토콜을 통하여 **순회 방법을 일원화**하였다. + - [[33. 7번째 데이터 타입 Symbol|Symbol]] 을 이용하여 메소드를 직접 구현하거나, 프로토타입 체인을 통해 `Symbol.iterator`에 접근시 **이터레이터**를 반환 + - **이터레이터** : `next` 메소드를 가지며, 메소드 호출시 `value`와 `done` 프로터피를 갖는 **Result 객체** +### 34.1.1 이터러블 +> 이터러블(Iterable) 프로토콜을 준수한 객체 + +- 이터러블 객체는 `for ... or` 문으로 순회할 수 있으며, [[35. 스프레드 문법|스프레드 문법]] 과 [[36. 디스트럭처링 할당|디스트럭처링 할당]]의 대상으로 사용될 수 있다. +``` javascript +const [a, ...rest] = array; +console.log(a, rest); // 1, [2, 3] +``` + +### 34.1.2 이터레이터 +> `Symbol.iterator` 메소드 호출시, 이터레이터 프로토콜을 준수한 **이터레이터를 반환**한다. + +- 이터레이터는 `next` 메소드를 갖는다. + - `next` 메소드는, 각 요소를 순회하기 위한 포인터의 역할을 한다. + - `next` 메소드 호출시, `value` 와 `done` 의 프로퍼티를 갖는 객체를 반환한다. + - `value` : 실제 값 + - `done` : 완료 여부 +## 34.2 빌트인 이터러블 + +## 34.3 for...of 문 +> 이터러블 객체는 `for...or` 문으로 순회할 수 있다. + +- `for...in` 문은 모든 프로토타입의 프로퍼티 중, `[[Enumerable]]`이 `true`인 프로퍼티를 순회한다. +- `for...of`문은 `next` 메소드를 호출하여 반환된 **Result 객체**의 `value` 프로퍼티를 변수에 할당한다. + - `Done` 이 `true` 이면 이터러블의 순회를 중단한다. +## 34.4 이터러블과 유사 배열 객체 +- **유사 배열 객체** : 인덱스로 프로퍼티 값에 접근할 수 있고 `length` 프로퍼티를 갖는 객체 +``` javascirpt +const arrayLike = { + 0: 1, + 1: 2, + 2: 3, + length: 3 +} + +console.log(arrayLike[2]); // 3 +``` +- 유사 배열 객체는 이터러블일 수도 있다. +## 34.5 이터레이션 프로토콜의 필요성 +## 34.6 사용자 정의 이터러블 +- **사용자 정의 이터러블**: 이터러블을 준수하지 않은 일반 객체가 이터레이션 프로토콜을 구현한 경우 + +### 34.6.1 사용자 정의 이터러블 구현 +- 이렇게 직접 구현하고 사용할 수 있다. +``` javascript +const fibonacci = { + [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 fibonacci) { + console.log(num); // 1 2 3 5 8 +} +``` +### 34.6.2 이터러블을 생성하는 함수 +- 외부에서 값을 받아, 이터러블을 반환하는 함수를 만들면 더욱 깔끔하다. +``` javascript +const fibonacciFunc = function (max) { + let [pre, cur] = [0, 1]; + + return { + [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 fibonacci) { + console.log(num); // 1 2 3 5 8 +} +``` + +### 34.6.3 이터러블이면서 이터레이터인 객체를 생성하는 함수 +### 34.6.4 무한 이터러블과 지연 평가 +- 이터러블은 **지연 평가**(`Lazy evaluation`) 을 통해 데이터를 생성한다. + - **지연 평가** : 데이터가 필요한 시점에서야 데이터를 생성하는 기법 + + +# 35장: 스프레드 문법 +> `...`을 통하여 하나로 뭉쳐있는 여러 값들의 집합을 펼쳐, 개별적인 값들의 목록으로 만드는 문법 + +``` javascript + +console.log(...[1, 2, 3]); // 1, 2, 3 +console.log(...'Hello') // H e l l o + +// 이터러블이 아닌 일반 객체는 스프레드 문법의 대상이 아니다 +console.log(... {a : 1, b: 2 }) +``` + +- 스프레드 문법의 결과는 **값이 아니기 때문에 변수에 할당할 수 없다.** +## 35.1 함수 호출문의 인수 목록에서 사용하는 경우 +- 목록으로 펼쳐서 인수 목록으로 전달할 때 유용하다. +``` javascript +consoe.log(Math.max(...[1, 2, 3])); +``` + +## 35.2 배열 리터럴 내부에서 사용하는 경우 + +### 35.2.1 concat +- ES5에서 사용하던 `concat` 메소드를 더욱 효과적으로 사용할 수 있다. +``` javascript +// ES5 +var arr = [1, 2].concat([3, 4]) +console.log(arr) + +// ES6 +const arr = [...[1, 2], ...[3, 4]]; +console.log(arr) +``` +### 35.2.2 splice +- ES5에서 사용하던 `splice` 메소드를 더욱 효과적으로 사용할 수 있다. +``` javascript +// ES6 +var arr1 = [1, 4] +var arr2 = [2, 3] + +arr1.splice(1, 0, ...arr2) +console.log(arr1); // [1, 2, 3, 4] +``` +### 35.2.3 배열 복사 +``` javascript +const origin = [1, 2]; + +// 얕은 복사 +const copy = [...origin] + +console.log(copy); // [1, 2] +``` +### 35.2.4 이터러블을 배열로 변환 + +## 35.3 객체 리터럴 내부에서 사용하는 경우 +- 곧 표준 사양으로 올라올 **스프레드 프로퍼티**를 이용하면 객체 리터럴에서도 스프레드 문법을 사용할 수 있다. + - 스프레드는 이터러블이어야 하지만, **스프레드 프로퍼티는 일반 객체를 대상으로 스프레드 문법을 허용** +``` javascript +const merged = { x : 1, y : 2, ...{ a: 3, b : 4} } +console.log(merged) +``` + + +# 36장: 디스트럭처링 할당 +> [[34. 이터러블|이터러블]] 또는 객체를 디스트럭처링(Destructuring)하여 1개 이상의 **변수에 개별적으로 할당**하는 것. +## 36.1 배열 디스트럭처링 할당 +``` javascript +const arr = [1, 2, 3] + +const [one, two, three] = arr; + +// 1. 기본값을 할당할 수 있다 +const [a, b, c = 3] = [1, 2] + +// 1.1 당연히, 할당값이 우선이다 +const [a, b, c = 3] = [1, 2, 4] +console.log(c) // 4 + +// 2. rest 파라미터를 사용할 수 있다. +const [x, ...y] = [1, 2, 3]; +console.log(x, y); // 1, [2, 3] +``` + +## 36.2 객체 디스트럭처링 할당 +- 객체의 프로퍼티 키를 기준으로 할당할 수 있다. +``` javascript +const obj = { + a : 1, + b : 2, +} + +const { a , b } = obj; + +console.log(a, b) // 1, 2 +``` + +- 객체를 인수로 전달받는 매개변수에서도 적용이 가능하다. +``` javascript +function printTodo({ content, completed }) { + console.log(content, completed) +} + +printTodo({ id : 1, content: 'content', completed: true }) +``` + +- 배열과 객체 디스트럭처링을 섞어서 사용할 수 있다. +``` javascript +const user = { + name: 'Lee', + address: { + zipCode: '03068', + city : 'Seoul' + } +}; + +const { address: { city } } = user; +console.log(city); +``` + + +# 37장: Set과 Map +## 37.1 Set +> 중복되지 않은 유일한 값들의 집합 +### 37.1.1 Set 객체의 생성 +- `Set` 생성자 함수는 [[34. 이터러블|이터러블]] 을 인수로 전달받아 `Set` 객체를 생성 +``` javascript +new Set([1, 2, 3, 4, 5]) +new Set('hello') + +new Set([1, 2, 3, 3, 5]) // {1, 2, 3, 5} +``` +### 37.1.2 요소 개수 확인 +> `Set.prototype.size`를 통해 요소의 개수를 확인할 수 있다. + +- 접근자 프로퍼티이기 때문에, 숫자를 변경할 수 없다. +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +console.log(set.size); // 10 + +set.size = 5 +console.log(set.size); // 10 +``` +### 37.1.3 요소 추가 +> `Set.prototype.add` 메소드를 통해 요소를 추가한다. + +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +console.log(set.size); // 10 + +set.add(11); +console.log(set) // Set { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } +``` +### 37.1.4 요소 존재 여부 확인 +> `Set.prototype.has` 메소드를 통해 특정 요소가 존재하는 지 확인한다 + +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + +console.log(set.has(5)); // true +``` +### 37.1.5 요소 삭제 +> `Set.prototype.delete` 메소드를 통해 특정 요소를 삭제한다. + +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + +set.delete(5); +console.log(set); // Set { 1, 2, 3, 4, 6, 7, 8, 9, 10 } +``` +### 37.1.6 요소 일괄 삭제 +> `Set.prototype.clear` 메소드를 통해 일괄 삭제한다. + +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + +set.clear(); +console.log(set); // Set {} +``` +### 37.1.7 요소 순회 +> `Set.prototype.forEach` 메소드를 통해 순회할 수 있다. + +- 이 때, 3개의 인자를 받게 된다. + - `v` : 현재 순회 중인 요소 값 + - `v2` : 현재 순회 중인 요소 값 + - `set` : 순회중인 set 객체 +`forEach` 호환성을 준수하기 위하 다음과 같이 설계하였다. +``` javascript +const set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + +set.forEach((v, v2, set) => console.log(v, v2, set)) +``` + +- `Set` 객체는 [[34. 이터러블|이터러블]] 이기 때문에 스프레드 문법과 배열 디스트럭처링의 대상이 될 수 있다. +### 37.1.8 집합 연산 +> 구현되어 있는 건 없지만, 함수형 언어 잘 써서 구현할 수 있다. +## 37.2 Map +### 37.2.1 Map 객체의 생성 +> `Map` 생성자 함수로 생성할 수 있다 + +``` javascript +const map = new Map() +console.log(map) // Map {} + +// 중복된 값이 있다면 덮어써진다. +const map2 = new Map([['name', 'John'], ['age', 30]]) +console.log(map2) // Map { 'name' => 'John', 'age' => 30 } +``` +### 37.2.2 요소 개수 확인 +``` javascript +const map = new Map([['name', 'John'], ['age', 30]]) +console.log(map.size) +``` +### 37.2.3 요소 추가 +> `Map.prototype.set` 메소드를 사용해서 추가할 수 있다. + +``` javascript +const map = new Map([['name', 'John'], ['age', 30]]) +map.set('job', 'developer') +console.log(map) // Map { 'name' => 'John', 'age' => 30, 'job' => 'developer' } +``` +### 37.2.4 요소 취득 +> `Map.prototype.get` 메소드를 통해서 획득할 수 있다. + +``` javascript +const map = new Map([['name', 'John'], ['age', 30]]) +console.log(map.get('name')) // John +``` + +### 37.2.5 요소 존재 여부 확인 +> `Map.prototype.has` 메소드를 통해서 존재 여부를 확인할 수 있다. + +``` javascript +const map = new Map([['name', 'John'], ['age', 30]]) +console.log(map.has('name')) // true +``` + +### 37.2.6 요소 삭제 +> `Map.prototype.delete` 메소드를 통해 삭제할 수 있다. + +``` javascript +const map = new Map(['key', 'value']) +map.delete('key') +console.log(map.has('key')) // false +``` +### 37.2.7 요소 일괄 삭제 +> `Map.prototype.clear` 메소드를 통해 일괄로 날릴 수 있다. + +``` javascript +const map = new Map(['key', 'value']) +map.clear() +console.log(map.size) // 0 +``` + +### 37.2.8 요소 순회 +> `Map.prototype.forEach` 메소드를 통해 순회할 수 있다. + +- 이 때, 3개의 인자를 받게 된다. + - `v` : 현재 순회 중인 요소 값 + - `k` : 현재 순회 중인 요소 키 + - `map` : 순회중인 map 객체 +`forEach` 호환성을 준수하기 위하 다음과 같이 설계하였다. +``` javascript +const map = new Map([['key', 'value'], ['key2', 'value2']]); + +map.forEach((v, k, map) => console.log(v, k, map)); +``` +