ES6 Symbol 오브젝트

ES6 Symbol 오브젝트

목차

Comment

Symbol에 대해서 이해가 안갔는데 C언어의 enum과 비슷한 개념이라고 설명한 부분에서 살짝 감이 왔다.


ECMAScript6 책 (두고두고 보는 자바스크립트 표준 레퍼런스)
인프런 JavaScript ES6+ 제대로 알아보기 – 중급 :: symbol


심볼은 3가지 형태로 사용할 수 있다.

  1. Symbol(): Symbol 값을 생성하며 스코프 안에서 사용한다.
  2. Symbol.for(): 글로벌 Symbol registry에 저장되며 전체 프로그램에서 사용한다.
  3. 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();
  1. new 연산자를 사용하지 않는다.
  2. Symbol()로 생성된 값은 프로그램 전체를 통해 유일하고, 값을 변경할 수 없다.(immutable)
    • C언어의 enum과 비슷한 개념이다.
  3. 생성한 Symobol에 프로퍼티를 설정할 수 없다.
  4. 반환자가 오브젝트가 아니므로, 오브젝트를 생성한다고 할 수 없다.
    • symbol값을 생성한다는 표현이 적절하다.
  5. String의 '', Array의 [] 처럼 Symbol을 생성하는 리터럴이 없다.
    • undefined와 null 처럼 그 자체가 값이 되는 것도 아니다.
    • 함수로 호출해야 값을 생성하여 반환한다. Symbol()
  6. Symbol()로 값을 생성하고 출력하면, Symbol()로 생성한 값을 반환하지 않고, Symbol 값을 생성했던 형태를 반환한다. 이는 symbol의 특징이다.
  7. Symbol값을 외부에 노출시키지 않는 것이 Symbol의 특징이다.
  8. Symbol()로 생성한 값의 설명이나 주석을 문자열로 작성한다.
    Symbol값을 외부에 제공하지 않으므로 디버깅할 때 유용하다.
    파라미터를 작성하지 않으면 undefined로 인식한다.
1
2
3
4
5
feature1: const sym = Symbol();
feature6: sym // Symbol()
feature_: typeof sym // symbol
feature8: Symbol("주석") // Symbole(주석)
feature2: sym == Symbole() // false

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
2
3
4
5
6
let sym = Symbol("123");
let obj = {[sym]: "456"};
console.log(obj); // {Symbol(123): "456"}

console.log(obj[sym]); // 456
console.log(obj.sym); // undefined

대괄호를 사용하지 않고 obj.sym 형태로 작성하면 에러는 안나지만 undefined가 반환된다.

  • Symbol을 키로 갖는 프로퍼티를 <<>>형태로 표기하고 있다.

6. Symbol 사용형태

for-in 문에서 symbol-keyed property는 열거되지 않는다.

6.1 for-in 문에서 Symbol 사용 (외부스코프에서 의미없는 키값 => symbol화)

1
2
3
4
5
6
7
8
9
10
let obj = {nine: 999};
obj[Symbol("one")] = 111;
obj[Symbol("two")] = "222";
console.log(obj);

for (const key in obj){
console.log(key)
}
// {nine: 999, Symbol(one): 111, Symbol(two): "222"}
// nine

일반적으로 for-in문으로 객체를 순회하면서 symbol-keyd property는 접근할 수 없다.
때문에 객체의 고유한 식별자로써, 상수개념으로 사용한다.
외부 스코프에서 의미가 있지 않는 값들만 symbol화 시킨다.
은닉화의 목적이 있기때문에 외부 스코프에서는 접근가능하지 않아야하지만 내부에서는 가능하도록 만들어야한다.

  • Object.getOwnPropertySymbols()를 사용하여 symbol-keyed property 키값들을 열거할 수 있다.
  • Reflect.ownKeys를 사용하면 symbol-keyed property 키와 값까지 알 수 있다.

6.2 클래스 메서드 이름으로 Symbol 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const symbolOne = Symbol("symbol one");
const symbolTwo = Symbol("symbol two");

class Sports {
static [symbolOne](){
return "Symbol-1";
}
[symbolTwo]() {
return "Symbol-2";
}
}

console.log(Sports[symbolOne]());

const obj = new Sports();
console.log(obj[symbolTwo]());

6.3 JSON.stringify()에서 Symbol 사용

1
2
3
let sym = Symbol("key");
let result = JSON.stringify({[sym]: "값"});
console.log(result); // {}

빈 오브젝트가 반환된다.
이는 Symbol 값을 외부에 노출되지 않도록 하기 위한 조치이다.

6.4 프로퍼티 은닉화

  • symbol로 정의된 키값에는 바로 접근이 불가능하다.
  • 키값이 들어있는 프로퍼티를 객체 내부에 적용해놓으면 심볼 키에 접근가능하다.
1
2
3
4
5
6
7
const x = () => {
const a = Symbol('a');
return {
[a]: 10,
a: a,
}
}

7. Symbol.for

public member 전역공간에서 공유되는 심볼.
여기저기서 많이 사용되는 공용상수를 사용할때 사용

1
2
3
4
5
6
7
8
const a = Symbol.for('abc') 
// 새로 생성해서 넣음.
console.log(a) // "Symbol(abc)"
const b = Symbol.for('abc')
// 기존에 'abc' 식별자로 되어있는 symbol을 찾아서 있으면 넣어준다.
console.log(b) // "Symbol(abc)"

a === b // true

?! a와 b가 값과 타입이 같다고 나온다.
Symbol.for는 for의 인자를 식별자로 사용한다.

1
2
3
4
5
6
7
8
const obj1 = (() => {
const COMMON1 = Symbol.for('공유심볼')
return {
[COMMON1]: '공유할 프로퍼티 키값. 어디서든 접근 가능'
}
})();
obj1[Symbol.for('공유심볼')]
// "공유할 프로퍼티 키값. 어디서든 접근 가능"
📚