symbol

ᄋᄋ·2021년 12월 19일
0

출처: MDN

1. 자바스크립트는 객체 프로퍼티 키로 오직 문자형과 심볼형만을 허용함( 숫자형, 불린형 모두 불가능).

2. '심볼(symbol)'은 유일한 식별자(unique identifier)를 만들고 싶을 때 사용함.

let id = Symbol();     // id는 새로운 심볼이 됨.

3. 심볼을 만들 때 '심볼 이름'이라 불리는 '설명'을 붙일 수도 있음. 심볼 이름은 디버깅 시 아주 유용함.

let id = Symbol("id");      // 심볼 id에는 "id"라는 설명이 붙음.

4. 심볼은 유일성이 보장되는 자료형이기 때문에, 설명이 동일한 심볼을 여러 개 만들어도 각 심볼값은 다름. 심볼에 붙이는 설명(심볼 이름)은 어떤 것에도 영향을 주지 않는 이름표 역할만을 함.

let id1 = Symbol("id");
let id2 = Symbol("id");
id1 == id2; // false

5. 심볼은 문자형으로 자동 형변환이 되지 않음.

자바스크립트에선 문자형으로의 암시적 형 변환이 비교적 자유롭게 일어나는 편임.
그래서 alert 함수가 거의 모든 값을 인자로 받을 수 있는 거임. 그러나 심볼은 예외임. 심볼형 값은 다른 자료형으로 암시적 형 변환(자동 형 변환)되지 않음.

아래 예시에서 alert는 에러를 발생시킴.

let id = Symbol("id");
alert(id);      // TypeError: Cannot convert a Symbol value to a string

문자열과 심볼은 근본이 다르기 때문에 우연히라도 서로의 타입으로 변환돼선 안 됨. 자바스크립트에선 '언어 차원의 보호장치(language guard)'를 마련해 심볼형이 다른 형으로 변환되지 않게 막아줌.

심볼을 반드시 출력해줘야 하는 상황이라면 아래와 같이 .toString() 메서드를 명시적으로 호출해주면 됨.

let id = Symbol("id");
alert(id.toString());       // Symbol(id)가 alert창에 출력됨.

toString()이란?
obj.toString() === String(obj)     // '[object Object]'
참고로, 숫자 or BigInt.toString(2 ~ 36)
*2, 8, 10, 16 진법으로 변환

symbol.description 프로퍼티를 이용하면 설명만 보여주는 것도 가능함.

let id = Symbol("id");
alert(id.description);       // id

6. ‘숨김’ 프로퍼티

심볼을 이용하면 ‘숨김(hidden)’ 프로퍼티를 만들 수 있음. 숨김 프로퍼티는 외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없는 프로퍼티임.

서드파티 코드에서 가지고 온 user라는 객체가 여러 개 있고, user를 이용해 어떤 작업을 해야 하는 상황이라고 가정해 보자. user에 식별자를 붙여주도록 하자.

식별자는 심볼을 이용해 만들도록 하겠음.

let user = {     // 서드파티 코드에서 가져온 객체
  name: "John"
};

let id = Symbol("id");
user[id] = 1;
alert( user[id] );   // 심볼을 키로 사용해 데이터에 접근할 수 있다.

그런데 문자열 "id"를 키로 사용해도 되는데 Symbol("id")을 사용한 이유가 무엇일까?
user는 서드파티 코드에서 가지고 온 객체이므로 함부로 새로운 프로퍼티를 추가할 수 없음. 그런데 심볼은 서드파티 코드에서 접근할 수 없기 때문에, 심볼을 사용하면 서드파티 코드가 모르게 user에 식별자를 부여할 수 있음.

상황 하나를 더 가정해보자면, 제3의 스크립트(자바스크립트 라이브러리 등)에서 user를 식별해야 하는 상황이 벌어졌다고 해보자.
user의 원천인 서드파티 코드, 현재 작성 중인 스크립트, 제3의 스크립트가 각자 서로의 코드도 모른 채 user를 식별해야 하는 상황이 벌어졌다면?

제3의 스크립트에선 아래와 같이 Symbol("id")을 이용해 전용 식별자를 만들어 사용할 수 있음.

// ...
let id = Symbol("id");
user[id] = "제3 스크립트 id 값";

심볼은 유일성이 보장되므로 우리가 만든 식별자와 제3의 스크립트에서 만든 식별자가 충돌하지 않음. 이름이 같더라도 그러함.

만약 심볼 대신 문자열 "id"를 사용해 식별자를 만들었다면 충돌이 발생할 가능성이 있음.

let user = { name: "John" };

// 문자열 "id"를 사용해 식별자를 만들었음.
user.id = "스크립트 id 값";

// 만약 제3의 스크립트가 우리 스크립트와 동일하게 문자열 "id"를 이용해 식별자를 만들었다면...

user.id = "제3 스크립트 id 값"
// 의도치 않게 값이 덮어 쓰여서 우리가 만든 식별자는 무의미해짐.

6 - 1. Symbols in a literal

객체 리터럴 {...}을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 함.

<예시>
let id = Symbol("id");

let user = {
  name: "John",
  [id]: 123      //"id": 123은 안됨
};

"id": 123이라고 하면, 심볼 id가 아니라 문자열 "id"가 키가 됨.

profile
개발자A

0개의 댓글