본문 바로가기

Javascript

JS 에서의 Symbol 의 사용과 응용

1. symbol 과 상수

예제로 symbol 을 어떤 경우에 사용할수 있는지 알아보자.

import { log } from "console";

// 이 경우에는 value 인 1,2,3,4 에는 의미가 없고 상수의 이름자체에 의미가 있다.
const Direction_1 = {
  up: 1,
  down: 2,
  left: 3,
  right: 4,
};

const myDirection_1 = Direction_1.up;

if (myDirection_1 === Direction_1.up) {
  log("up!"); // up!
}

// 이 경우 문제는 상수 값 1,2,3,4 가 변경될수 있으며,
// 다른 변수값과 중복 될 수도 있다는 것이다.
// 이러한 경우 변경 / 중복될 가능성이 있는 무의미한 상수 대신 symbol 을 사용할수 있다.

const Direction_2 = {
  up: Symbol("up"),
  down: Symbol("down"),
  left: Symbol("left"),
  right: Symbol("right"),
};

const myDirection_2 = Direction_2.up;

if (myDirection_2 === Direction_2.up) {
  log("up!!"); // up!!
}

2. symbol 로 프로퍼티 키 만들기

const obj = {
  // 심볼 값으로 프로퍼티 키를 생성
  [Symbol.for("mySymbol")]: 1,
};

log(obj[Symbol.for("mySymbol")]); // 1

symbol 은 유일한 값이기 때문에, 다른 프로퍼티 키와 절대 충돌하지 않는다.

기존 프로퍼티나 미래에 추가될 프로퍼티도 마찬가지이다.

3. 빌트인 객체의 확장

빌트인 객체 ( ex : Array.prototype ) 에 custom 메서드를 직접 추가 하여 확장하는것은 권장 되지 않는데, 그 이유는 나중에 추가될 메서는의 이름이 중복되어는 문제가 생길수 있기 때문이다.

하지만 symbol 값으로 프로퍼티 키를 생성하고 확장하게 되면 그런 문제가 없다.

// 심볼 값으로 프로퍼티 키를 동적 생성하면 다른 프로퍼티 키와 절대 충돌하지 않아 안전하다.
Array.prototype[Symbol.for('sums')] = function () {
    return this.reduce((acc, cur) => acc + cur, 0)
}

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

4. Well-Known-Symbol

JS 가 기본 제공하는 빌트인 symbol 값이 있다.

이 빌트인 symbol 값은 Symbol 함수의 프로퍼티에 할당 되어있다.

이런 빌트인 symbol 값을 ECMAScript 사양에서 Well-Known-Symbol 이라고 부른다.

Well-Known-Symbol 은 대표적으로 Symbol.iterator 등이 있다.

이터러블이 아닌 객체를 이터러블 처럼 동작하도록 구현 할수도 있다.

// 1 ~ 5 범위를 가진 이터러블
const iterable_1 = {
  [Symbol.iterator]() {
    let cur = 1;
    const max = 5;

    return {
      next() {
        return { value: cur++, done: cur > max + 1 };
      },
    };
  },
};

for (const num of iterable_1) {
  log(num); // 1 2 3 4 5
}

이때 일반 객체에 추가하는 Symbol.iterator 프로퍼티는 기존 프로퍼티나 미래에 추가될 프로퍼티와 절대 중복되지 않는다.

이처럼 symbol 은 중복되지 않는 상수 값을 생성 하고, 기존 코드에 영향을 주지 않고 새로운 프로퍼티를 추가 하는,

하위 호환성을 보장하기 위해 도입되었다.