ES6에서 도입된 7번째 원시 데이터 타입(primitive).
심벌은 다른 값과 중복되지 않는 유일무이한 값임.
따라서 주로 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용한다.
프로퍼티 키로 사용할 수 있는 값은 빈 문자열을 포함하는 모든 문자열 또는 심벌 값임.
심벌 값은 Symbol 함수를 호출하여 생성한다.
다른 원시값 (문자열, 숫자, 불리언, undefined, null) 들은 리터럴 표기법을 통해 값을 생성할 수 있지만, 심벌 값은 Symbol 함수만으로 호출하여 생성할 수 있다.
이 때 생성된 심벌 값은 외부로 노출되지 않나 확인 불가능하고, 다른 값과 절대 중복되지 않는 유일무이한 값임.
const mySymbol = Symbol();
console.log(typeof mySymbol);
// symbol;
console.log(mySymbol)
// Symbol();
생성자 함수로 객체를 생성하는 것이 아님.
new 연산자와 함께 호출하지 않음.
new 연산자와 함께 생성자 함수 또는 클래스를 호출하면 객체(인스턴스)가 생성되지만 심벌 값은 변경 불가능한 원시 값임.
new Symbol();
//TypeError: Symbol is not a constructor
Symbol 함수에는 선택적으로 문자열을 인수로 전달가능.
설명, 디버깅 용도로만 사용되고, 심벌 값 생성에 어떠한 영향도 주지 않는다.
즉, 설명이 같더라도 생성된 심벌 값은 유일무이한 값임.
const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');
console.log(mySymbol1 === mySymbol2);
//false
심벌 값도 string, number, boolean 같이 객체처럼 접근하면 암묵적으로 래퍼 객체를 생성함.
const mySymbol = Symbol('mySymbol');
console.log(mySymbol.description);
// mySymbol
console.log(mySymbol.toString());
// Symbol(mySymbol)
자바스크립트 엔진이 관리하는 전역 심볼 레지스트리는 사용 가능한 모든 심볼이 저장되어 있다. 레지스트리에 접근할 수 있는 함수로는 Symbol.for, Symbol.keyFor 메서드가 있다.
이 메서드들은 전역 심볼 레지스트리 테이블과 런타임 환경 사이에서 심볼 값을 전해주는 역할을 한다. 전역 심볼 레지스트리는 대부분 자바스크립트 컴파일 인프라에 내장되어 있고, 레지스트리 내용은 자바스크립트 런타임 환경에서는 Symbol.for, Symbol.keyFor 메서드를 사용하지 않고서는 접근이 불가능하다.
const Direction = {
Up: 1,
Down: 2,
Left: 3,
Right: 4,
};
const Direction = {
UP: Symbol('up'),
DOWN: Symbol('down'),
LEFT: Symbol('left'),
RIGHT: Symbol('right')
};
위처럼 특별한 의미가 없고 상수 이름 자체에 의미가 있는 경우. 상수 1,2,3,4가 변경될 수 있고, 다른 변수 값과 중복될 위험도 있다. 이러한 경우 중복/변경 가능성이 있는 무의미한 상수 대신 중복될 가능성이 없는 유일무이한 심벌 값을 사용할 수 있다.
또한 JS에서 enum을 흉내내어 사용할려면, Object.freeze메서드와 심벌 값을
const id = Symbol('myId');
const obj = {
[id] : 'myId',
name : 'soso'
}
객체의 프로퍼티 키의 조건은?
빈 문자열을 포함하는 모든 문자열 또는 심벌 값.
심벌 값을 프로퍼티 키로 사용할 경우 심벌 값에 대괄호를 사용해야 한다. 접근할 때도 마찬가지.
심벌 값을 프로퍼티 키로 사용해 생성한 프로퍼티는 for ...in 문이나 Object.keys.object.getOwnPropertyNames 메서드로 찾을 수 없다.
따라서 외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있다.
단, ES6에서 도입된 Object.getOwnPropertySymbols 메서드를 사용하면 심벌 값을 프로퍼티 키로 사용해 생성한 프로퍼티를 찾을 수 있다.
const obj = {
[Symbol.for('mySymbol')]: 1
};
obj[Symbol.for('mySymbol')]; // 1
Array.prototype.sum= function () {
return this.reduce((acc,cur) => acc + cur, 0);
};
[1,2].sum(); // 3
Array.prototype[Symbol.for('sum') = function () {
return this.reduce((acc. cur) => acc + cur, 0);
};
자바스크립트가 기본 제공하는 빌트인 심벌값을 Well-known Symbols라고 부른다. 이는 자바스크립트 엔진의 내부 알고리즘에 사용된다.
Array, Map, Set 등이 이에 해당된다.
예를 들어 Well-known Symobl인 Symbol.iterator를 키로 갖는 메서드를 객체에 추가하고 이터레이터를 반환하도록 구현하면 그 객체는 이터러블이 된다.
이 외에도 instanceof 메서드를 사용할 때 호출되는 Symbol.hasInstance, String.prototype.match를 호출할 때 사용되 Symbol.match 등 자바스크립트 내부에서 유일한 값을 찾아내야할 때 내부적으로 사용되는 다양한 Well-known Symbols가 있다.
이처럼 심벌은 중복되지 않는 상수 값을 생성하는 것은 물론 기존에 작성된 코드에 영향을 주지 않고 새로운 프로퍼티를 추가하기 위해, 즉 하위 호환성을 보장하기 위해 도입되었다.