Symbol
심볼(Symbol) 데이터 타입은 ES6 이전에도 존재했지만, 이제 직접적으로 심볼을 사용할 수 있는 공식 인터페이스가 제공됩니다. 심볼은 고유한 기본 값(primitive value)으로 수정 불가능한(immutable) 데이터 타입이고, 클래스나 객체의 내부에서만 접근할 수 있도록 비공개 키(private key)로 사용됩니다. 예를 들면 사용자가 정의한 클래스(custom classes)는 심볼을 사용해 비공개 속성(private members)을 만들 수 있습니다.
{
// 블록 스코프 내에서만 접근 가능한 심볼
const _privateKey = Symbol();
// 글로벌에 공개된 클래스
window.FileReader = class {
constructor() {
this[_privateKey]();
}
[_privateKey]() {
console.log('비공개 멤버로 클래스 FileReader 만 접근하여 사용 가능');
}
}
}
const fileReader = new FileReader(); // '비공개 멤버로 클래스 FileReader 만 접근하여 사용 가능'
fileReader[_privateKey](); // Uncaught ReferenceError: _privateKey is not defined
Symbol()
Symbol()
또는 Symbol([description])
이 실행되어 반환되는 모든 심볼 값은 고유합니다.
심볼 값은 객체 프로퍼티(object properties)에 대한 식별자로 사용될 수 있습니다.
이것이 심볼 데이터 형식의 유일한 목적입니다.
주의!
심볼은 new Symbol()
문법을 제공하지 않습니다.
const symbol = new Symbol(); // TypeError: Symbol is not a constructor
Symbol()
은 써드 파티(third-party) 라이브러리의 객체 혹은 네임스페이스에 충돌할 염려가 없는 새로운 코드를 덧입히는데 종종 쓰입니다.
예를 들어, 나중에 라이브러리가 업데이트 되더라도 겹칠 우려가 없이 React.Component
클래스에 refreshComponent
메서드를 추가하고
싶다면 다음과 같이 할 수 있습니다.
const refreshComponent = Symbol();
React.Component.prototype[refreshComponent] = () => {
// ...
};
Symbol.for(key)
Symbol.for(key)
는 고유하고 수정 불가능한 심볼을 생성하지만, 전역적으로 사용할 수 있습니다.
Symbol.for(key)
를 2번 호출하면 2번 모두 동일한 심볼 인스턴스를 반환합니다.
Symbol('y9') === Symbol('y9'); // false
Symbol.for('y9') === Symbol('y9'); // false
Symbol.for('y9') === Symbol.for('y9'); // true
주의!
Symbol([description])
의 결과는 Symbol.for(key)
와 동일하지 않습니다.
Symbol('y9') === Symbol('y9'); // false
Symbol.keyFor(globalSymbol)
Symbol.keyFor(globalSymbol)
메서드는 전달된 글로벌 심볼의 공유 키를 검색 반환합니다.
const globalSymbol = Symbol.for('y9'); // 글로벌 심볼
const localSymbol = Symbol('y9'); // 로컬 심볼
console.log(Symbol.keyFor(globalSymbol)); // 'y9'
console.log(Symbol.keyFor(localSymbol)); // undefined
상호 운용성
일반적으로 심볼, 특히 Symbol.for(key)
는 상호 운용성(Interoperability)을 위해 사용합니다. 상호 운용성은 몇 가지 알려진
인터페이스를 포함하는 써드 파티 라이브러리의 객체에 인자로 심볼 멤버 형태의 코드를 사용함으로서 만족될 수 있습니다.
예를 들어 써드 파티 라이브러리의 reader
함수 내부에 글로벌 심볼 specialRead
을 전달 인자 객체 obj
의 속성(함수 타입)을 식별하고,
메서드로 사용하는 구문이 있습니다.
function reader(obj) {
const specialRead = Symbol.for('specialRead');
if (obj[specialRead]) {
const reader = obj[specialRead]();
// ...
} else {
throw new TypeError('객체를 읽을 수 없습니다.');
}
}
다른 써드 파티 라이브러리 또한 글로벌 심볼 specialRead
를 사용해 클래스 SomeReadableType
의 메서드를
정의합니다.
const specialRead = Symbol.for('specialRead');
class SomeReadableType {
[specialRead]() {
const reader = createSomeReaderFrom(this);
return reader;
}
}
상호 운용성을 위해 심볼을 사용하는 주목할 만한 예는 반복 가능한(iterable) 모든 데이터 타입 또는
반복자(iterator)에 존재하는 Symbol.iterator
입니다. 배열, 문자열, 생성자 등
반복 가능한 타입은 이 메서드를 통해 호출되면 반복자 인터페이스를 포함한 객체 형태로 반환 됩니다.