34. [JavaScript] 심볼(Symbol)
property key는 문자형(string)으로 처리됩니다.
const obj = {
1: '1입니다.',
false:'거짓'
}
Object.keys(obj); // ["1", "false"]
실제로 접근할 때도 문자열로 접근할 수 있습니다.
obj['1'] // "1입니다."
obj['false'] // "거짓"
문자열 말고 하나 더 가능한 것이 심벌형(Symbol)입니다.
심벌은 유일한 식별자를 만들 때 사용합니다.
console로 확인해보면 Symbol()이라는 같은 값을 표시하지만 일치 연산자(===)나 동등 연산자(==)로 확인해보면 false를 리턴합니다.
심벌형은 유일성이 보장됩니다. 전체 코드 중에 딱 하나라는 뜻입니다.
심벌을 만들 때 설명을 붙여줄 수도 있습니다. 설명을 붙여주면 디버깅할 때 편합니다.
설명은 문자열로 붙여주면 되고 이 문자열은 심벌 생성에 어떠한 영향도 미치지 않습니다.
설명이 같은걸 2개 만들면 어떻게 될까요?
생긴 거는 똑같지만 둘 다 다른 값을 가지고 있다고 나옵니다.
Proprty key : 심벌형
심벌형을 사용하여 키를 할당해 보겠습니다.
const id = Symbol('id');
const user = {
name:"Mike",
age:30,
[id]:"myid"
}
console.log(user); // {name:"Mike", age:30, Symbol(id):"myid"}
이전 시간에 배웠던 Object.keys(), Object.values(), Object.entries()는 키가 심벌형인 프로퍼티는 건너뜁니다.
마찬가지로 for ... in을 써도 건너뜁니다.
Object.keys(user); // ["name", "age"]
Object.values(user); // ["Mike", 30]
Object.entries(user); // [Array(2), Array(2)]
이렇게 꽁꽁 숨겨져 있는 것을 어디에 쓸 수 있을까요?
특정 객체의 원본 데이터를 건드리지 않고 데이터를 수정할 수 있습니다.
다른 사람이 만든 객체에 덮어 씌우는 것은 좋지 않습니다.
그렇다고 엄청 긴 이름의 키값을 주는 것도 좋지 않습니다.
그리고 나중에 for... in으로 어디선가 객체의 프로퍼티가 호출될 수도 있기 때문에 중간에 프로퍼티를 추가하는 작업은 신중하게 해야 합니다.
Symbol.for() : 전역 심벌
이렇게 심벌을 이름이 같더라도 모두 다른 존재입니다.
그런데 가끔 전역 객체처럼 이름이 같으면 같은 객체를 가리킬 때가 있습니다.
이럴 때 사용할 수 있는 것이 Symbol.for입니다.
특징
- 하나의 심벌만 보장받을 수 있음
- 없으면 만들고, 있으면 가져오기 때문
- Symbol 함수는 매번 다른 Symbol 값을 생성하지만,
- Symbol.for 메서드는 하나를 생성한 뒤 키를 통해 같은 Symbol을 공유
const id1 = Symbol.for('id');
const id2 = Symbol.for('id');
console.log(id === id2); // true
이름을 호출하고 싶다면 아래 코드를 사용하면 됩니다.
keyFor()을 이용해서 변수 이름을 넣어주면 생성할 때 작성한 이름을 알려줍니다.
Symbol.keyFor(id1); // "id"
전역 심벌이 아닌 심벌은 keyFor을 사용할 수 없습니다.
대신 description으로 저 이름을 알 수 있습니다.
const id = Symbol('id 입니다.');
id.description; // "id 입니다."
사실 Symbol을 완전히 숨기는 방법을 없습니다.
Object.getOwnPropertySymbols를 사용하면 심벌들만 볼 수 있습니다.
Reflect.ownKeys는 심벌형 키를 포함한 객체의 모든 키를 보여줍니다.
const id = Symbol('id');
const user = {
name:"Mike",
age:30,
[id]:"myid"
}
Object.getOwnPropertySymbols(user); // [Symbol(id)]
Reflect.ownKeys(user); // ["name","age",Symbol(id)]
그런데 대부분의 라이브러리, 내장 함수들은 이런 키를 사용하지 않습니다.
그러므로, 유일한 프로퍼티를 추가하고 싶을 때 심벌을 사용하시면 됩니다.
아래와 같은 코드가 있다고 가정합니다.
[내가 작업]한 코드와 [사용자가 접속하면 보이는 메시지] 사이에 간격이 있다고 가정하고 내가 중간에 프로퍼티를 추가하면 위와 같이 의도치 않은 데이터가 사용자에게 노출되어 버립니다.
이런 경우 Symbol을 써주면 됩니다.
이렇게 하면 의도치 않는 데이터가 노출되는 것을 방지할 수 있습니다.
사용할 때는 아래 코드를 입력하면 됩니다.
user[showName](); // Mike