Starting with ECMAScript 2015,
symbol
is a primitive data type, just likenumber
andstring
.symbol
values are created by calling theSymbol
constructor.
Symbol이라는 데이터 타입이 있다.
Symbol(””)
는 심볼을 새로 생성 (절대로 이렇게 생성된건 같아질 수 없다)
Symbol.for(””)
는 심볼 레지스터리에 있는 심볼 반환
Unique한 키가 필요하면서도 안의 값이 필요하다 할 때 쓴다고 한다.
예를 들어서 특정 기능을 하는 함수와 함수 이름을 키로써 갖는 맵이 (i.e. Map<String, Function>) 같은게 있다고 했을때,
어느 순간 함수 이름이 겹쳐질 경우 기존의 Function이 덮어써질 수 있다.
그런 의도하지 않은 상황을 피하기 위해 Symbol이라는 유니크한 값을 쓴다고 한다.
Object.keys를 사용하면 오브젝트 내의 문자열로 된 키값은 반환하지만, Symbol로 된 키는 반환하지 않는다.
따라서 Symbol 객체를 key의 iterator로 꺼내고 싶다면, Object.getOwnPropertySymbols 를 사용해야 한다.
예를 들면,
const myObject = {
[Symbol('foo')]: 'bar',
baz: 'qux'
};
console.log(Object.keys(myObject)); // ["baz"]
console.log(Object.getOwnPropertySymbols(myObject)); // [Symbol(foo)]
한편, 위의 특징을 바탕으로 Object.keys에는 노출되지 않기에 의도적으로 프레임워크/라이브러리 내부에 데이터를 숨기기 위해서도 Symbol을 사용할 수 있다고 한다.
기본적으로 Unique Symbol끼리는 비교할 수 없다.
const sym1 = Symbol.for('sym'); //unique symbol
const sym2 = Symbol.for('sym'); //unique symbol
let sym3 = Symbol.for('sym');
let sym4 = Symbol.for('sym');
이때, sym == sym2 는 비교 불가능 (false가 나오는게 아니라 애초에 컴파일 불가)
Unique Symbol의 주 목적은 “고유성” 이기때문에, 불변성과 보안을 강화하기 위한 주 목적의 설계상 비교할 수 없도록 되어있다고 한다.
한편 앞의 생성하는 방법에서 언급된 Symbol(””)과 Symbol.for(””) 을 비교해보자면,
let symbol1 = Symbol.for('mySymbol');
let symbol2 = Symbol.for('mySymbol');
console.log(symbol1 === symbol2); // true
let symbolA = Symbol('mySymbol');
let symbolB = Symbol('mySymbol');
console.log(symbolA === symbolB); // false
이지만 물론 const나 readonly같은 불변 변수로 선언될 경우 비교할 수 없다.