33. 7번째 데이터 타입 Symbol

2023. 1. 19. 21:35기록/Modern JavaScript Deep Dive

    목차

심벌이란?

ES6 에서 도입된 7번째 데이터 타입
변경 불가능한 원시 타입의 값
다른 값과 중복되지 않는 유일무이한 값
주로 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용함

심벌 값의 생성

1. Symbol 함수

const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol

// 심벌 값은 외부로 노출되지 않아 확인 불가능
console.log(mySymbol); // Symbol

// 심벌 값에 대한 설명이 같더라도 유일무이한 심벌 값을 생성함
const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');

console.log(mySymbol1 === mySymbol2); // false

 

2. Symbol.for / Symbol.keyFor 메서드

Symbol.for

인수로 전달받은 문자열을 키로 사용하여
키와 심벌 값의 쌍들이 저장되어 있는
전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색함
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값 생성
const s1 = Symbol('mySymbol');

// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 있으면 해당 심벌 값 반환
const s2 = Symbol('mySymbol');

console.log(s1 === s2); // true

 

검색에 성공 시 새로운 심벌 값을 생성하지 않고 검색된 심벌 값을 반환함

검색에 실패 시 새로운 심벌 값을 생성하여 Symbol.for 메서드의 인수로 전달된 키로

전역 심벌 레지스트리에 저장한 후, 생성된 심벌 값을 반환함

 

Symbol.keyFor

전역 심벌 레지스트리에 저장된 심벌 값의 키 추출 가능
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값 생성
const s1 = Symbol.for('mySymbol');

// 전역 심벌 레지스트리에 저장된 심벌 값의 키 추출
Symbol.keyFor(s1); // mySymbol

// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않음
const s2 = Symbol('foo');

// 전역 심벌 레지스트리에 저장된 심벌 값의 키 추출
Symbol.keyFor(s2); // undefined

심벌과 상수

심벌 값을 사용하여 상수 값의 변경/중복될 가능성을 제거함

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

심벌과 프로퍼티 은닉

심벌 값을 프로퍼티 키로 사용해 생성한 프로퍼티는 for ... in 문이나

Object.keys, Object.getOwnPropertyNames 메서드로 찾을 수 없음

외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있음

 

ES6에서 도입된 Object.getOwnPropertySymbols 메서드를 사용하면

심벌 값을 프로퍼티 키로 사용하여 생성한 프로퍼티를 찾을 수 있음

const obj = {
  [Symbol.for('mySymbol')]: 1
}

for (const key in obj) {
  console.log(key); // 아무것도 출력되지 않음
}

console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []

심벌과 표준 빌트인 객체 확장

중복될 가능성이 없는 심벌 값으로 프로퍼티 키를 생성하여 표준 빌트인 객체를 확장하면

표준 빌트인 객체의 기존 프로퍼티 키와 충돌하지 않으며

표준 사양의 버전이 올라감에 따라 추가될지 모르는 어떤 프로퍼티 키와도 충돌할 위험이 없음

Array.prototype[Symbol.for('sum')] = function () {
  return this.reduce((acc, cur) => acc + cur, 0);
}

[1, 2][Symbol.for('sum')](); // 3

Well-known Symbol

자바스크립트가 기본 제공하는 빌트인 심벌 값을

ECMAScript 사양에서는 Well-known Symbol 라고 부름

Well-known Symbol는 자바스크립트 엔진의 내부 알고리즘에 사용됨