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 입니다. 배열, 문자열, 생성자 등 반복 가능한 타입은 이 메서드를 통해 호출되면 반복자 인터페이스를 포함한 객체 형태로 반환 됩니다.

참고