Comment
Symbol에 대해서 이해가 안갔는데 C언어의 enum과 비슷한 개념이라고 설명한 부분에서 살짝 감이 왔다.
ECMAScript6 책 (두고두고 보는 자바스크립트 표준 레퍼런스)
인프런 JavaScript ES6+ 제대로 알아보기 – 중급 :: symbol
심볼은 3가지 형태로 사용할 수 있다.
- Symbol(): Symbol 값을 생성하며 스코프 안에서 사용한다.
- Symbol.for(): 글로벌 Symbol registry에 저장되며 전체 프로그램에서 사용한다.
- Well-Known Symbol: 빌트인 Symbol 프로퍼티로 오버라이드하여 기능을 추가, 변경할 수 있다.
1. primitive
string, number, boolean은 레퍼(Wrapper) 오브젝트가 있다.
- string은 String
- number는 Number
- boolean은 Boolean
- es6에서 symbol의 Symbol 오브젝트가 추가되었다.
wrapper 오브젝트는 vlaueOf()로 프리미티브 값을 구할 수 있지만, symbol은 값을 반환하지 않는다.
2. Symbol()
Symbol([description])
- description: 설명, 주석
- 반환값: 유니크한 Symbol 값
1 | let sym = Symbol(); |
- new 연산자를 사용하지 않는다.
- Symbol()로 생성된 값은 프로그램 전체를 통해 유일하고, 값을 변경할 수 없다.(immutable)
- C언어의 enum과 비슷한 개념이다.
- 생성한 Symobol에 프로퍼티를 설정할 수 없다.
- 반환자가 오브젝트가 아니므로, 오브젝트를 생성한다고 할 수 없다.
- symbol값을 생성한다는 표현이 적절하다.
- String의
''
, Array의[]
처럼 Symbol을 생성하는 리터럴이 없다.
- undefined와 null 처럼 그 자체가 값이 되는 것도 아니다.
- 함수로 호출해야 값을 생성하여 반환한다.
Symbol()
- Symbol()로 값을 생성하고 출력하면, Symbol()로 생성한 값을 반환하지 않고, Symbol 값을 생성했던
형태를 반환한다.
이는 symbol의 특징이다. - Symbol값을 외부에 노출시키지 않는 것이 Symbol의 특징이다.
- Symbol()로 생성한 값의 설명이나 주석을 문자열로 작성한다.
Symbol값을 외부에 제공하지 않으므로 디버깅할 때 유용하다.
파라미터를 작성하지 않으면undefined
로 인식한다.
1 | feature1: const sym = Symbol(); |
3. Symbol 값 변경
- Symbol()로 생성한 Symbol값은 변경할 수 없다.
- Symbol값에 문자열을 추가하고 싶을 경우 Symbol을 toString()이나 String()으로 변환한 후 연결해야한다.
4. Symbol 오브젝트 생성
Object(123)처럼 Object()의 파라미터에 123을 지정하면 Number 오브젝트를 반환한다.
- Object() 파라미터에 Symbol 값을 지정하면 Symbol 오브젝트를 반환한다.
- Symbol 오브젝트에 Symbol메서드, Symbol.prototype, protototype에 연결된 프로퍼티가 설정된다.
5. 오브젝트에서 Symbol 사용
유일한 값을 갖는 Symbol 특성을 활용하여
Symbol 값을 오브젝트의 프로퍼티 키로 사용하면 프로퍼티
키가 중복되지 않습니다.
symbol-keyed property
[Symbol()]
형태와 같이 대괄호 안에 Symbol()을 작성
1 | {[Symbol()]: 123} |
이렇게 프로퍼티 키에 작성한 Symbol()을 **symbol-keyed property
**라고 한다.
{ ABC: 123 }
에서ABC
에 Symbol값을 넣은 것이다.
여기서 Symbol값은 문자열이 아니라 그냥 Symbol값이라고 생각하면된다.
1 | let sym = Symbol("123"); |
대괄호를 사용하지 않고 obj.sym
형태로 작성하면 에러는 안나지만 undefined
가 반환된다.
- Symbol을 키로 갖는 프로퍼티를
<<>>
형태로 표기하고 있다.
6. Symbol 사용형태
for-in 문에서 symbol-keyed property는 열거되지 않는다.
- Symbol이
[[Enumerable]]: false
이기 때문.
(객체의 데이터 프로퍼티에서[[Enumerable]]
은 기본적으로 true이다.)
6.1 for-in 문에서 Symbol 사용 (외부스코프에서 의미없는 키값 => symbol화)
1 | let obj = {nine: 999}; |
일반적으로 for-in문으로 객체를 순회하면서 symbol-keyd property는 접근할 수 없다.
때문에 객체의 고유한 식별자로써, 상수개념으로 사용한다.
외부 스코프에서 의미가 있지 않는 값들만 symbol화 시킨다.
은닉화의 목적이 있기때문에 외부 스코프에서는 접근가능하지 않아야하지만 내부에서는 가능하도록 만들어야한다.
Object.getOwnPropertySymbols()
를 사용하여 symbol-keyed property 키값들을 열거할 수 있다.Reflect.ownKeys
를 사용하면 symbol-keyed property 키와 값까지 알 수 있다.
6.2 클래스 메서드 이름으로 Symbol 사용
1 | const symbolOne = Symbol("symbol one"); |
6.3 JSON.stringify()에서 Symbol 사용
1 | let sym = Symbol("key"); |
빈 오브젝트가 반환된다.
이는 Symbol 값을 외부에 노출되지 않도록 하기 위한 조치이다.
6.4 프로퍼티 은닉화
- symbol로 정의된 키값에는 바로 접근이 불가능하다.
- 키값이 들어있는 프로퍼티를 객체 내부에 적용해놓으면 심볼 키에 접근가능하다.
1 | const x = () => { |
7. Symbol.for
public member 전역공간에서 공유되는 심볼.
여기저기서 많이 사용되는 공용상수를 사용할때 사용
1 | const a = Symbol.for('abc') |
?!
a와 b가 값과 타입이 같다고 나온다.Symbol.for
는 for의 인자를 식별자로 사용한다.
1 | const obj1 = (() => { |