AnnSEo.log

[Deep Dive] 33장 Symbol 본문

자바스크립트

[Deep Dive] 33장 Symbol

AnnSEo2105 2021. 10. 3. 16:04

ES6에 도입된 7번째 데이터 타입으로 premitive 타입이며 다른 값과 중복되지 않는 유일무이한 값이다. 유일한 객체의 프로퍼티 키(property key)를 만들기 위해 사용된다.

 

객체의 Private한 property를 가능하게 하기 위해서 시작 → 심볼을 참조하지 않고는 액세스 할 수 없는 프로퍼티 만드는데 사용

33.2 Symbol 값의 생성

  • Symbol() 함수를 호출해 값을 생성하며 빌트인 객체의 여러 멤버를 가리키는 정적 프로퍼티와 global symbol registry를 가리키는 정적 메서드를 가진다. 
  • 모든 심볼 값은 고유하므로 객체 프로퍼티에 대한 식별자로 사용될 수 있다. → 심볼의 고유 목적 
  • 원시 값이기 때문에 → 객체 생성 X, new 연산자 사용 X(new 연산자 사용 시 TypeError 발생)

새로운 심볼 값 대신 명시적으로 심볼 래퍼 객체를 생성할 수 없게함, 즉 생성자로 사용할 수 없음

일반적으로 premitive 데이터 형에 대한 명시적인 래퍼 객체 생성이 가능하다는 점을 생각하면 의외일 수 있으나(ex) new Boolean, new String 등) 심볼 값은 new를 쓰지 못한다는 점!

꼭 심볼 래퍼 객체를 생성하고 싶으면 Object() 함수를 이용할 수 있다.

 

  • 문자열을 인수로 전달할 수 있음 → 생성된 Symbol 값에 대한 설명으로 디버깅 용도로만 사용되며 값 생성에 영향을 주진 않음
  • 외부로 값이 노출되지 않아 확인할 수 없다.
  • 객체처럼 접근하면 암묵적으로 래퍼 객체를 생성
  • Symbol 값은 암묵적으로 문자열이나 숫자 타입으로 변환되지 않으나 boolean 타입으로는 암묵적 타입 변환된다.

 

parameter

description Optional

// Symbol 함수 호출해 Symbol 값 생성
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol

// 외부로 노출되지 않음
console.log(mySymbol); // Symbol()

// 인수로 설명 전달(디버깅 용도)
const mySymbol1 = Symbol("mySymbol");

// 래퍼 객체 생성함
console.log(mySymbol1.description); // mySymbol
console.log(mySymbol.toString()); // Symbol(mySymbol)

// 암묵적으로 boolean 타입으로 변환된다.(문자열이나 숫자 타입은 안됌)
console.log(!!mySymbol); // true

 

Symbol에 파라미터로 같은 값을 쓰더라도 심볼 생성에 영향을 주진 않는다. 

아래 코드는 3개의 새로운 심볼을 생성하고 Symbol("foo")는 "foo"라는 문자열을 심볼로 강제로 변환시키지 않는다.

var sym1 = Symbol();
var sym2 = Symbol("foo");
var sym3 = Symbol("foo");

Symbol("foo") === Symbol("foo"); // false

 

 

Global Symbol Registry 내의 심볼 공유

Symbol() 함수를 이용해서 생성한 심볼은 전체에서 사용 가능한 전역 심볼을 생성하는 것은 아니다. 

파일 간, 램 간에도 사용할 수 있는 심볼을 생성하기 위해서는 Symbol.for()와 Symbol.keyFor() 메서드를 이용해 전역 심볼 레지스트리에 심볼을 설정하거나 추출해야 한다.

  • Symbol.for(key)
    • 주어진 key로 현재 존재하는 심볼을 검색하고 찾으면 반환. 존재하지 않으면 주어진 키로 전역 심볼 레지스트리에 새로운 심볼을 생성하고 그 심볼을 반환
    • global symbol registry는 자바스크립트 엔진이 관리하는 심벌 값 저장소인데 심벌 값을 검색할 수 있는 키를 지정할 수 없으므로 이 저장소에 등록되어 관리되지 않는다. 하지만 Symbol.for 메서드를 사용하면 애플리케이션 전역에 중복되지 않는 유일무이한 상수인 심벌 값을 단 하나만 생성해 전역 심벌 레지스트리를 통해 공유할 수 있다.
  • Symbol.keyFor(sym)
    • global symbol registry에 저장된 심볼에 대한 공유 심볼 키(shared symbol key)를 추출

 

// global symbol registry에 mySymbol이라는 키로 저장된 symbol 값이 없으므로 
// 새로운 symbol 값 생성
const s1 = Symbol.for("mySymbol");
// mySymbol 키로 저장된 symbol 값이 있으므로 그 symbol 값을 반환
const s2 = Symbol.for("mySymbol");

console.log(s1 === s2); // true
const s1 = Symbol.for("mySymbol");
const s2 = Symbol("foo");

// s2는 Symbol 함수를 호출해 생성한 Symbol 값으로 
// global Symbol registry에 등록되어 관리되지 않음
// Symbol.keyFor(): global Symbol registry에 저장된 Symbol 값의 키를 추출
Symbol.keyFor(s1); // mySymbol
Symbol.keyFor(s2); // undefined

 

33.3 Symbol과 상수

값에는 의미가 없고 상수 이름 자체에 의미가 있는 경우 Symbol 값 사용 가능

 

 

33.4 Symbol과 프로퍼티 키

객체의 프로퍼티 키는 빈 문자열을 포함하는 모든 문자열 외에 심벌 값으로도 만들 수 있으며 동적 생성도 가능하다. 대괄호를 사용해서 만들고 접근할 때도 대괄호를 사용해야 한다.

Symbol 값이 유일무이한 값이므로 다른 프로퍼티 키와 절대 충돌하지 않는다.(현재 있는 것부터 미래 생성될 것까지 포함해서)

 

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

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

 

 

33.5 Symbol과 프로퍼티 은닉

Symbol 값을 프로퍼티 키로써 생성한 프로퍼티는 for...in 문이나 Object.keys, Object.getOwnPropertyNames 메서드로 찾을 수 없어 프로퍼티를 은닉할 수 있다.

단, ES6에 도입된 Object.getOwnPropertySymbols 메서드를 사용하면 인수로 전달한 객체의 Symbol 프로퍼티 키를 배열로 반환해 프로퍼티와 Symbol 값을 찾을 수 있다.

 

33.6 Symbol과 표준 빌트인 객체 확장

표준 빌트인 객체는 read-only로 사용하는게 좋다. 미래에 표준 사양으로 추가될 메서드 이름이 덮어쓰기 될 수도 있기 때문.

하지만 중복될 가능성이 없는 Symbol 값을 프로퍼티 키로 생성해 표준 빌트인 객체를 확장하면 기존 프로퍼티 키와도 충돌하지 않으면서 표준 사양 버전이 up되도 추가될 어떤 프로퍼티 키와도 충돌할 위험이 없어 안전하게 확장할 수 있다.

 

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

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

 

 

33.7 Well-known Symbol

자바스크립트가 기본 제공하는 빌트인 Symbol 값이 있는데 Symbol 함수의 프로퍼티에 할당되어 있다. 이 기본 제공하는 빌트인 Symbol 값을 ECMAScript 사양에서는 Well-known-Symbol이라 부른다. 자바스크립트 엔진 내부 알고리즘에 사용된다.

 

결국 Symbol로 중복되지 않는 상수 값을 생성해 기존 작성된 코드에 영향을 주지 않으면서 새로운 프로퍼티를 추가하게 된다. 이렇게 하위 호환성은 보장하기 위해 도입.

'자바스크립트' 카테고리의 다른 글

[Deep Dive] 34장 이터러블  (0) 2021.10.04
[Deep Dive] 28장 Number  (0) 2021.09.26
[Deep Dive] 24장 클로저  (0) 2021.09.19
[Deep Dive] 19장 프로토타입  (0) 2021.09.14
[Deep Dive] 21장 빌트인 객체  (0) 2021.09.12