출처: MDN
let id = Symbol(); // id는 새로운 심볼이 됨.
let id = Symbol("id"); // 심볼 id에는 "id"라는 설명이 붙음.
let id1 = Symbol("id");
let id2 = Symbol("id");
id1 == id2; // false
자바스크립트에선 문자형으로의 암시적 형 변환이 비교적 자유롭게 일어나는 편임.
그래서 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
심볼을 이용하면 ‘숨김(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 값"
// 의도치 않게 값이 덮어 쓰여서 우리가 만든 식별자는 무의미해짐.
객체 리터럴 {...}을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 함.
<예시>
let id = Symbol("id");
let user = {
name: "John",
[id]: 123 //"id": 123은 안됨
};
"id": 123
이라고 하면, 심볼 id가 아니라 문자열 "id"가 키가 됨.