문자열
, 숫자
, 불리언
, undefined
, null
, 객체 타입
Symbol
ES6에서 도입된 7번째 데이터 타입, 변경 불가능한 원시타입 값
Symbol
Symbol 값은 Symbol
함수를 호출하여 생성
문자열
, 숫자
, 불리언
, undefined
, null
타입 값은 리터럴 표기법을 통해 값 생성이 가능하지만
Symbol 값은 Symbol
함수를 호출하여 생성❗️
Symbol 값은 외부로 노출되지 않아 확인할 수 X
다른 값과 절대 중복되지 않는 유일무이한 값
new
연산자와 함께 호출하지 않음 (생성자 함수로 객체 생성 X)
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol
// Symbol 값은 외부 노출 X
console.log(mySymbol); // Symbol()
// new 연산자와 함께 사용 X
new Symbol(); // TypeError: Symbol is not a constructor
Symbol
함수에 선택적으로 문자열을 인수로 전달할 수 있음const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');
console.log(mySymbol1 === mySymbol2); // false
Symbol
값은 암묵적으로 문자열이나 숫자 타입으로 변환되지 않음
하지만, boolean
값으로는 암묵적 타입 변환 가능
if
문에서 존재 확인const mySymbol = Symbol();
console.log(mySymbol + ''); // TypeError: Cannot convert a Symbol value to a string
console.log(+mySymbol); // TypeError: Cannot convert a Symbol value to a string
console.log(!!mySymbol);
if (mySymbol) console.log('mySymbol is not empty.');
Symbol.for
메서드
인수로 전달받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색
검색에 성공하면 새로운 심벌 값을 생성하지 않고 검색된 심벌 값 반환
검색에 실패하면 새로운 심벌 값을 생성하여 Symbol.for
메서드의 인수로 전달된 키로 전역 심벌 레지스트리에 저장한 후, 생성된 심벌 값 반환
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값 생성
const s1 = Symbol.for('mySymbol');
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 있으면 해당 심벌 값 반환
const s2 = Symbol.for('mySymbol');
console.log(s1 === s2); // true
Symbol.keyFor
메서드
전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있음
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 생성
const s1 = Symbol.for('mySymbol');
Symbol.keyFor(s1); // mySymbol
// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않음
const s2 = Symbol('foo');
Symbol.keyFor(s1); // undefined
값에는 특별한 의미가 없고 상수 이름 자체에 의미가 있는 경우,
변경·중복될 가능성이 있는 무의미한 상수 대신 중복될 가능성이 없는 유일무이한 심벌 값 사용
전
const Direction = {
UP: 1,
DOWN: 2,
LEFT: 3,
RIGHT: 4
};
const myDirection = Direction.UP;
if (myDirection === Direction.UP) {
console.log('You are going UP');
}
const Direction = {
UP: Symbol('up'),
DOWN: Symbol('down'),
LEFT: Symbol('left'),
RIGHT: Symbol('right')
};
const myDirection = Direction.UP;
if (myDirection === Direction.UP) {
console.log('You are going UP');
}
심벌 값을 프로퍼티 키로 사용하려면 프로퍼티 키로 사용할 심벌 값에 대괄호 사용
프로퍼티에 접근할 때도 마찬가지로 대괄호 사용
심벌 값은 유일무이한 값이므로 심벌 값으로 프로퍼티 키를 만들면 다른 프로퍼티 키와 절대 충돌하지 않음
const obj = {
[Symbol.for('mySymbol')]:1
};
obj[Symbol.for('mySymbol')]; // 1
const obj = {
[Symbol.for('mySymbol')]:1
};
for (const key in obj) {
console.log(key);
}
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []
Object.getOWnPropertySymbols
메서드를 사용하여 심벌 값을 프로퍼티 키로 사용하여 생성한 프로퍼티를 찾을 수 있음const obj = {
[Symbol.for('mySymbol')]:1
};
// getOwnPropertySymbols : 인수로 전달한 객체의 심벌 프로퍼티 키를 배열로 반환
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(mySymbol)]
// getOwnPropertySymbols 메서드로 심벌 값도 찾을 수 있음
const symbolKey1 = Object.getOwnPropertySymbols(obj)[0];
console.log(obj[symbolKey1]); // 1
표준 빌트인 객체에 사용자 정의 메서드를 직접 추가하여 확장하는 것은 권장하지 않음 ❗️
→ 직접 추가한 메서드와 미래 표준 사양으로 추가될 메서드의 이름이 중복될 수 있기 때문
중복될 가능성이 없는 심벌 값으로 프로퍼티를 생성하여 표준 빌트인 객체를 확장하면 충돌 위험 ❌
Array.prototype[Symbol.for('sum')] = function () {
return this.reduce((acc, cur) => acc + cur, 0);
};
[1, 2][Symbol.for('sum')](); // 3
Well-known Symbol
자바스크립트가 기본 제공하는 빌트인 심벌 값
Well-known Symbol
는 자바스트립트 엔진의 내부 알고리즘에 사용됨
for...of
문으로 순회 가능한 빌트인 이터러블은 Symbol.iterator
를 키로 갖는 메서드를 가지며, Symbol.iterator
를 호출하면 이터레이터를 반환
만약 빌트인 이터러블이 아닌 일반 객체를 이터러블처럼 동작하도록 구현하고 싶다면 이터레이션 프로토콜을 따르면 됨
→ Well-known Symbol
인 Symbol.iterator
를 키로 갖는 메서드를 객체에 추가하고 이터레이터를 반환하도록 구현