-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)); | ||
``` | ||
|