자바스크립트는 객체 프로퍼티 키로 문자형과 심볼형만을 허용한다. 숫자형, 불린형 모두 불가능하다.
Symbol은 ES6에 새로 추가된 원시 타입이다. 심볼은 유일한 식별자를 만들고 싶을 때 사용한다.
for ... in
Object.keys(obj)
Object.getOwnPropertyNames(obj)
에 걸리지 않는다.참고로 심볼을 아예 볼 수 없는 것은 아니고 Object.getOwnPropertySymbols()
메서드로 심볼을 찾을 수 있다.
Symbol()
함수에는 문자열을 인자로 전달할 수 있다. 이 문자열은 Symbol
생성에 어떠한 영향을 주지 않고, 생성된 Symbol
에 대한 설명(description)으로 디버깅 용도로만 사용된다.
const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');
console.log(mySymbol1 === mySymbol2); // false
console.log(mySymbol1.description); // 'mySymbol'
console.log(mySymbol1.description === mySymbol2.description); // true, description 끼리는 같다.
console.log(typeof mySymbol1); // 'symbol'
const symbolProp = Symbol('symbolProp');
const obj = {
prop1: 1,
[symbolProp]: 2,
};
for (const key in obj) console.log(key); // prop1
console.log(obj[symbolProp]); // 2 -> []로만 접근 가능
문자열 'symbolProp'을 객체의 키로 사용해도 되는데 Symbol('symbolProp')
으로 사용한 이유는 무엇일까?
obj가 다른 라이브러리에서 가져온 코드라고 했을 때, 그 객체에 새로운 key를 추가하고 싶을 수가 있을 것이다. 그런데 'symbolProp' 이라는 key가 이미 있다면 덮어 써질 것이다. 그러면 원래 있던 key가 사라지기 때문에 본래의 역할을 못 할수가 있다. 하지만 Symbol은 겹치지 않기 때문에 원래의 코드에 영향을 미치지 않는다.
Symbol.for(key)
Symbol.for()
메소드는 인자로 전달받은 문자열을 키로 사용하여 Symbol
값들이 저장되어 있는 전역 Symbol
레지스트리에서 해당 키와 일치하는 저장된 Symbol
값을 검색한다. 이때 검색에 성공하면 검색된 Symbol
값을 반환하고, 검색에 실패하면 새로운 Symbol
값을 생성하여 해당 키로 전역 Symbol
레지스트리에 저장한 후, Symbol
값을 반환한다.
// 전역 Symbol 레지스트리에 kwon라는 키로 저장된 Symbol이 없으면 새로운 Symbol 생성
const s1 = Symbol.for('kwon');
// 전역 Symbol 레지스트리에 kwon라는 키로 저장된 Symbol이 있으면 해당 Symbol을 반환
const s2 = Symbol.for('kwon');
console.log(s1 === s2); // true
Symbol
함수는 매번 다른 Symbol
값을 생성하는 것에 반해, Symbol.for()
메소드는 하나의 Symbol
을 생성하여 여러 모듈이 키를 통해 같은 Symbol
을 공유할 수 있다.
Symbol.for(key)
로 생성된 심볼은 전역 심볼 레지스트리에 저장되고, 꺼내오고 하기 때문에 전역에서 실행하든 함수에서 실행하든 똑같은 결과가 나오는 것을 확인할 수 있다.
function d() {
const c = Symbol.for('1234');
return c;
}
const c = d();
const f = Symbol.for('1234');
console.log(c === f); // true
Symbol.keyFor(sym)
전역 심볼 레지스트리로부터 주어진 심볼에 대한 공유 심볼 키(shared symbol key
)를 추출한다.
const sharedSymbol = Symbol.for('myKey');
const key1 = Symbol.keyFor(sharedSymbol);
console.log(key1); // myKey
console.log(sharedSymbol.description); // myKey
const unsharedSymbol = Symbol('myKey');
const key2 = Symbol.keyFor(unsharedSymbol);
console.log(key2); // undefined
console.log(unsharedSymbol.description); //myKey
Symbol.for()
메소드를 통해 생성된 Symbol
값은 반드시 키를 갖는다. 또한 키이자 description이 된다. 이에 반해 Symbol
함수를 통해 생성된 Symbol
값은 키가 없지만, description은 생긴다.
자바스크립트는 언어 내부의 동작을 나타내는 내장(built-in) 심볼을 몇 가지 가지고 있다.
Symbol.iterator
객체의 기본 반복자(default iterator)를 반환하는 메서드 for ... of
에서 사용됨.
Symbol.asyncIterator
객체의 기본 비동기 반복자(defaut AsyncIterator)를 반환하는 메서드 for await of
에서 사용 됨.
이외에도 많은 잘 알려진 심볼들이 있다.
참고
https://poiemaweb.com/es6-symbol
https://ko.javascript.info/symbol
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol
JS 스터디 중..