📢 자바스크립트는 객체 프로퍼티 키로 문자형과 심볼형만을 허용한다.
심볼(Symbol)
📢 유일한 식별자(unique identifier)를 만들고 싶을 때 사용한다.
let id = Symbol();
◾️ 심볼을 만들 때 심볼 이름이라 불리는 설명을 붙일 수도 있다. ✅ 디버깅시 아주 유용
let id = Symbol('id');
◾️ 심볼은 유일성이 보장되는 자료형이기 때문에, 설명이 동일한 심볼을 여러 개 만들어도 각 심볼값은 다르다.
let suzu = Symbol('name');
let ruru = Symbol('name');
console.log(suzu == ruru); // false
⚠️ 심볼은 문자형으로 자동 형 변환되지 않는다.
◾️ 자바스크립트에선 문자형으로의 암시적 형 변환이 비교적 자유롭게 일어나는 편이지만 심볼은 예외
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)
◾️ 심볼의 설명만 출력하고 싶을 때는 description 프로퍼티를 이용한다.
let id = Symbol('id');
alert(id.description); // id
'숨김' 프로퍼티
◾️ 심볼을 이용하면 숨김(hidden) 프로퍼티를 만들 수 있다.
◾️ 숨김(hidden) 프로퍼티 : 외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없는 프로퍼티
◾️ 문자열 'id' 대신 Symbol('id')를 사용한 이유
◾️ user는 서드파티 코드에서 가지고 온 객체이므로 함부로 새로운 프로퍼티를 추가할 수 없다.
◾️ 심볼은 서드파티 코드에서 접근할 수 없기 때문에 심볼을 사용하면 서드파티 코드가 모르게 user에 식별자를 부여할 수 있다.
// user에 심볼을 이용해 식별자를 만들어준다.
let user = { // 서드파티 코드에서 가져온 객체
name: 'suzu'
}
let id = Symbol('id');
user[id] = 1;
console.log( user[id] ); // 1
⚠️ 서드파티
하드웨어 생산자와 직접적인 관계없이 소프트웨어를 개발하는 회사를 서드 파티라고 부른다. 또는 하드웨어 생산자인 모기업과 자사간의 관계 또는 하청관계등 전혀 관련없는 소프트웨어 개발자를 써드 파티라고 부른다. _ wiki
◾️ 서드파티에서 가져온 객체 user, 현재 작성중인 스크립트, 제3의 스크립트(자바스크립트 라이브러리 등)가 각자 서로의 코드도 모른채 user를 식별해야 하는 상황일 때.
◾️ 제 3의 스크립트에선 Symbol('id')을 이용해 전용 식별자를 만들어 사용할 수 있다.
// ...
let id = Symbol('id');
user[id] = '제3의 스크립트의 id값';
◾️ 이름이 같더라도 심볼은 유일성이 보장되므로 우리가 만든 식별자와 제3의 스크립트에서 만든 식별자가 충돌하지 않는다.
객체 리터럴과 심볼
◾️ 객체 리터럴 { ... }을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 한다.
◾️ 'id: 123' 이라고 하면, 심볼 id가 아닌 문자열 id가 키가 된다.
let id = Symbol('id');
let user = {
name: 'suzu',
[id]: 123 // 'id:123' X
}
심볼은 for...in에서 배제된다.
◾️ 키가 심볼인 프로퍼티는 for .. in 반복문에서 배제된다.
let id = Symbol('id');
let user = {
name: 'suzu',
age: 30,
[id]: 123
};
for (let key in user) console.log(key); // name, age
// 심볼로 직접 접근
console.log( user[id] ); // 123
◾️ Object.keys(user)에서도 키가 심볼인 프로퍼티는 배제된다. (for...in과 같은 결과)
◾️ 심볼형 프로퍼티 숨기기(hiding symbolic property) 원칙 덕분에 외부 스크립트나 라이브러리는 심볼형 키를 가진 프로퍼티에 접근하지 못한다.
◾️ Object.assign은 키가 심볼인 프로퍼티를 배제하지 않고 객체 내 모든 프로퍼티를 복사한다.
let id = Symbol('id');
let user = {
[id]: 123
};
let clone = Object.assign({}, user);
console.log( clone[id] ); // 123
전역 심볼
◾️ 심볼은 이름이 같더라도 모두 별개로 취급되지만 이름이 같은 심볼이 같은 개체를 가리키길 원하는 경우도 있다.
◾️ 전역 심볼 레지스트리(global symbol registry) : 애플리케이션 곳곳에서 심볼 'id'를 이용해 특정 프로퍼티에 접근해야 할 때 사용
◾️ 전역 심볼 레지스트리 안에 심볼을 만들고 해당 심볼에 접근하면, 이름이 같은 경우 항상 동일한 심볼을 반환해 준다.
◾️ Symbol.for(key)를 호출하면 이름이 key인 심볼이 반환된다.
◾️ 조건에 맞는 심볼이 레지스트리 안에 없으면 새로운 심볼 Symbol(key)를 만들고 레지스트리 안에 저장한다.
// 전역 레지스트리에서 심볼을 읽는다.
let id = Symbol.for('id'); // 심볼이 존재하지 않으면 새로운 심볼을 만든다.
// 동일한 이름을 이용해 심볼을 다시 읽는다.
let idAgain = Symbol.for('id');
console.log( id === idAgain ); // true;
◾️ 전역 심볼 레지스트리 안에 있는 심볼을 전역 심볼이라 부른다. 광범위하게 사용해야 하는 심볼이라면 전역 심볼을 사용한다.
Symbol.keyFor
◾️ Symbol.keyFor(sym) : Symbol.for(key)에 반대되는 메서드. 이름을 얻을 수 있다.
// 이름을 이용해 심볼을 찾는다.
let sym = Symbol.for('name');
let sym2 = Symbol.for('id');
// 심볼을 이용해 이름을 얻는다.
console.log( Symbol.keyFor(sym) ); // name
console.log( Symbol.keyFor(sym2) ); // id
◾️ Symbol.keyFor는 전역 심볼 레지스트리를 뒤져서 해당 심볼의 이름을 얻어낸다. 전역 심볼이 아닌 심볼에는 사용할 수 없다.(undefined를 반환)
◾️ 일반 심볼에서 이름을 얻고 싶으면 description 프로퍼티를 사용한다.
let globalSymbol = Symbol.for('name');
let localSymbol = Symbol('name');
console.log( Symbol.keyFor(globalSymbol) ); // name
console.log( Symbol.keyFor(localSymbol) ); // undefined
console.log( localSymbol.description ); // name
시스템 심볼(system symbol)
◾️ 자바스크립트 내부에서 사용되는 심볼. 시스템 심볼을 활용하면 객체를 미세조정할 수 있다.
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.iterator
- Symbol.toPrimitive
- 기타 등등...
📝 요약
◽️ Symbol은 원시형 데이터로 유일한 식별자를 만드는데 사용된다.
◽️ Symbol() 메소드를 호출하여 심볼을 만든다. 설명(이름)은 옵션
◽️ 심볼은 이름은 같더라도 값이 항상 다르다.
◽️ 이름이 같을 때 값도 같길 원한다면 전역 레지스트리를 사용해야한다.
◽️ Symbol.for(key)는 key라는 이름을 가진 전역 심볼을 반환한다.
◽️ key라는 이름을 가진 전역 심볼이 없으면 새로운 전역 심볼을 만들어 준다.
◽️ key가 같다면 Symbol.for는 어디서 호출하든 상관없이 항상 같은 심볼을 반환해준다.
📝 오늘 새롭게 배운 내용 📝
✅ 심볼은 유니크한 존재다.
✅ 변수처럼 전역 심볼이라는 개념이 존재한다.
✅ 프로퍼티를 숨기고 싶을 때 사용할 수도 있다.
✅ 자바스크립트 내부에서 사용되는 심볼이 있다.
✅ 유스케이스는 이해했지만 실제로 어떻게 쓰일지...?
📌 [JAVASCRIPT_INFO 심볼형]
심볼형
ko.javascript.info
📌 [MDN Symbol]
Symbol
Symbol() 함수는 심볼(symbol) 형식의 값을 반환하는데, 이 심볼은 내장 객체(built-in objects)의 여러 멤버를 가리키는 정적 프로퍼티와 전역 심볼 레지스트리(global symbol registry)를 가리키는 정적 메서드
developer.mozilla.org
'모던 자바스크립트' 카테고리의 다른 글
6.1 재귀와 스택 (0) | 2020.08.15 |
---|---|
4.8 객체를 원시형으로 변환하기 (0) | 2020.08.13 |
4.6 옵셔널 체이닝 '?.' (0) | 2020.08.11 |
4.5 'new' 연산자와 생성자 함수 (0) | 2020.08.10 |
4.4 메서드와 'this' (0) | 2020.08.08 |