Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions 7주차/7주차_박시영.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#7주차
## 33: 7번째 데이터 타입 Symbol
Symbol: ES6에서 도입된 데이터 타입. 변경 불가능의 원시 타입이며, 다른 값과 중복되지 않음.

--> 이름 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용.
*프로퍼티 키로 사용 가능한 값은 모든 문자열 or 심벌 값이다.*

### 심벌 값의 생성
다른 리터럴 표기법으로 생성 가능한 원시값들과 달리 Symbol 함수를 호출해 생성해야만 함.

--> 생성된 값은 외부로 노출 x
```javascript
const mySymbol = Symbol();
// 생성자 함수처럼 생겼지만 new를 쓰지 않는다.
console.log(typeof mySymbol); // symbol

console.log(mySymbol); // Symbol()
```
- 인수로 문자열을 전달할 수 있지만, 생성된 값에 대한 설명으로 디버깅에만 쓰일 뿐임.
- 심벌 값은 암묵적으로 문자열 / 숫자 타입으로 변환 x.
- boolean으로는 변환 가능. (if문 등에서 존재 확인이 가능)

#### Symbol.for / Symbol.keyFor 메서트
Symbol.for은 **인수로 받은 문자열을 키로 사용해** 해당 키와 일치하는 심벌 값을 검색함.
- 검색 성공시 검색된 값을 반환
- 검색 실패시 새 심벌을 생성 후 그것을 반환

Symbol.keyFor을 쓰면 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있음.
```javascript
const s1 = Symbol.for('mySymbol');
const s2 = Symbol.for('mySymbol');
console.log(s1 === s2); //true

const s3 = Symbol.for('mySymbol');
const s4 = Symbol('foo');
Symbol.KeyFor(s3); // mySymbol
Symbol.KeyFor(s4); // undefined
// Symbol 함수를 통해 생성한 심벌 값은 전역 심벌 레지스트리에 등록되지 않음.
```

### 심벌과 상수
이를테면 UP: 1처럼 방향을 나타내는 상수를 정의한다고 할 때:
값에는 특별한 의미가 없고 이름 자체에 의미가 있는 경우, 상수 값이 변경되거나 타 값과 중복될 수 있다. 이 때 심벌 값을 사용할 수 있음.

```javascript
const Direction = {
UP: Symbol('up'),
DOWN: Symbol('down'),
LEFT: Symbol('left'),
RIGHT: Symbol('right')
};

const myDirection = Direction.UP;

if(myDirection === Direction.UP){
console.log('You are going UP.');
}
```

### 심벌과 프로퍼티 키
프로퍼티 키를 심벌 값으로 생성할 때,
```javascript
const obj = {
[Symbol.for('mySymbol')]: 1
};

obj[Symbol.for('mySymbol')]; // 1
```
사용할 심벌 값에 대괄호를 씌워야하며, 접근할 때도 대괄호를 사용해야 한다.

심벌 값을 프로퍼티 키로 써 만든 프로퍼티는 다음과 같은 메서드로는 찾을 수 없다:
- for ... in 문
- Object.keys
- Object
- getOwnPropertyNames

단, ES6에서 도입된 Object.getOwnPropertySymbols로는 찾을 수 있음.

### 심벌과 표준 빌트인 객체 확장
일반적으로 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가해 확장하는 것은 권장 x.
Why? --> 미래에 표준 사양으로 추가될 메서드의 이름이 중복될 수 있기 때문.

but 심벌 값으로 프로퍼티 키를 생성해 확장시 안전하게 이것을 진행할 수 있다.

### Well-known Symbol
:js에서 기본 제공하는 빌트인 심벌 값.
js 엔진의 내부 알고리즘에 사용됨.

ex) Array, String처럼 for ... of 문으로 순회 가능한 빌트인 이터러블
--> Symbol.iterator를 키로 갖는 메서드를 가짐. 이것을 호출하면 *이터레이터*를 반환하도록 ECMAScript 사양에 규정. (**이터레이션 프로토콜**)

## 34: 이터러블
### 이터레이션 프로토콜
순회 가능한 데이터 컬렉션 (**자료구죠**)를 만들기 위해 미리 약속한 규칙.
- 이터러블 프로토콜
Symbol.iterator를 프로퍼티 키로 사용한 메서드를 구현하거나 상속받은 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 *이터레이터*를 반환함. 이 규약을 이터러블 프로토콜이라고 하고, 이 프로토콜을 준수한 객체를 *이터러블*이라고 부른다.

- 이터레이터 프로토콜
이터레이터는 next 메서드를 소유함. 이 메서드를 호출하면 이터러블을 순회하며 value/done 프로퍼티를 갖는 *이터레이터 리절트 객체*를 반환함. 이 규약을 이터레이터 프로토콜이라고 하고, 이 프로토콜을 준수한 객체를 *이터레이터*라고 부른다.

- *이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할.*

```javascript
const isIterable = v => v !== null && typeof v[Symbol.iterator] === 'function';

isIterable([]); // true
isIterable(''); // true
isIterable(new Map()); // true
isIterable(new Set()); // true
isIterable({};) // false
```
ex) 배열은 Array.prototype의 Symbol.iterator 메서드를 상속받는 이터러블임.

```javascript
const array = [1, 2, 3];
const iterator = array[Symbol.iterator]();
console.log('next' in iterator); // true

console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
```
next 메서드 호출시 이터러블을 한 단계씩 순회하며 결과를 나타내는 **이터레이터 리절트 객체**를 반환한다.

### 빌트인 이터러블