on your mark
[JAVASCRIPT.INFO] 4.7 심볼형 본문
4.7 심볼형
심볼
'심볼(symbol)'은 유일한 식별자를 만들고 싶을 때 사용한다.
Symbol()
을 사용하면 심볼값을 만들 수 있다.
// id는 새로운 심볼이 된다.
// 심볼 id에는 "id"라는 설명이 붙는다.
let id = Symbol("id");
설명이 동일한 심볼을 여러 개 만들어도 각 심볼값은 다르다. 심볼에 붙이는 설명(심볼 이름)은 어떤 것에도 영향을 주지 않는 이름표 역할만 수행한다.
let id1 = Symbol("id");
let id2 = Symbol("id");
alert(id1 === id2) // false
심볼은 문자형으로 자동 형 변환되지 않는다.
자바스크립트에서 문자형으로의 암시적 형 변환이 비교적 자유로운 반면 심볼형 값은 다른 자료형으로 암시적 형 변환이 일어나지 않는다.let id = Symbol("id"); alert(id); // TypeError
문자열과 심볼은 근본이 다르기 때문에 우연히라도 서로의 타입으로 변환되어서는 안된다.
심볼을 반드시 출력해 줘야 하는 상황이라면
.toSring()
메서드를 이용해 명시적으로 호출해주면 된다.또는
symbol.description
프로퍼티를 이용하면 설명만 보여주는 것도 가능하다.let id = Symbol("id"); alert(id.toString()); // Symbol(id)가 얼럿 창에 출력됨 alert(id.description); // id
'숨김' 프로퍼티
심볼을 이요하면 'hidden' 프로퍼티를 만들 수 있다. hidden property는 외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없는 프로퍼티이다.
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의 스크립트에서 만든 식별자가 충돌하지 않는다. (이름이 같아도 충돌이 일어나지 않는다.)// .... let id = Symbol("id"); user[id] = "제 3스크립트 id 값"
만약 심볼대신 문자열
"id"
를 사용해 식별자를 만들었다면 충돌이 발생할 가능성이 있다.let user = { name: "John" }; user.id = "스크립트 id 값"; user.id = "제3 스크립트 id 값"; // 의도치 않게 값이 덮어 쓰여진다.
Symbols in a literal
객체 리터럴 {...}
을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 한다.
let id = Symbol("id");
let user = {
name: "John",
[id]: 123 // "id" : 123은 안됨
}
심볼은 for ... in 에서 배제된다.
let id = Symbol("id");
let user = {
name: "John",
age: 30,
[id]: 123 // "id" : 123은 안됨
}
for(let key in user) alert(key); // name과 age만 출력됨
alert("직접 접근: "+user[id]); // 심볼로 직접 접근하면 잘 작동함
Object.keys(user)
에서도 키가 심볼인 프로퍼티는 배제된다.
Object.assign
은 키가 심볼인 프로퍼티를 배제하지 않고 객체 내 모든 프로퍼티를 복사한다.
let clone = Object.assign({}, user);
alert(clone[id]); // 123
전역 심볼
이름이 같은 심볼이 같은 객체를 가리키길 원하는 경우, 전역 심볼 레지스트리를 활용한다.
전역 심볼 레지스트리 안에 심볼을 만들고 해당 심볼에 접근하면, 이름이 같은 경우 항상 동일한 심볼을 반환해준다.
레지스트리 안에 있는 심볼을 읽거나, 새로운 심볼을 생성하려면
Symbol.for(key)
를 사용한다. 이 메서드를 호출하면 이름이key
인 심볼을 반환한다. 조건에 맞는 심볼이 레지스트리 안에 없으면 새로운Symbol(key)
를 만들고 레지스트리 안에 넣는다.let id = Symbol.for("id"); // 전역 레지스트리에서 심볼을 읽고, 심볼이 존재하지 않아 새로운 심볼을 만든다. let idAgain = Symbol.for("id"); // 동일한 이름을 이용해 심볼을 다시 읽는다. alert(id === idAgain) // true
전역 심볼 레지스트리 안에 있는 심볼을 전역 심볼이라고 한다. 앱 내에서 광범위하게 사용해야 하는 심볼이라면, 전역 심볼을 사용하는 것이 좋다.
Symbol.keyFor
Symbol.keyFor(sym)
을 사용하면 이름을 얻을 수 있다.
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");
alert(Symbol.keyFor(sym)); // name
alert(Symbol.keyFor(sym2)); // id
검색 범위가 전역 심볼 레지스트리이기 때문에 전역 심볼이 아닌 심볼에 사용하면 undefined
를 반환한다.
일반 심볼에서 이름을 얻고 싶으면 description
을 사용하면 된다.
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");
alert(Symbol.keyFor(globalSymbol)); // name
alert(Symbol.keyFor(localSymbol)); // undefined
alert(localSymbol.description()); // name
시스템 심볼
자바스크립트 내부에서 사용되는 심볼이다. 시스템 심볼을 활용하면 객체를 미세 조정할 수 있다.
실제 사용 사례
'WEB > Javascript' 카테고리의 다른 글
[JAVASCRIPT.INFO] 5.1 원시값의 메서드 (0) | 2022.12.31 |
---|---|
[JAVASCRIPT.INFO] 4.8 객체를 원시형으로 변환하기 (0) | 2022.12.31 |
[JAVASCRIPT.INFO] 4.6 옵셔널 체이닝 '?.' (0) | 2022.12.28 |
[JAVASCRIPT.INFO] 4.5 new 연산자와 생성자 함수 (0) | 2022.12.28 |
[JAVASCRIPT.INFO] 4.4 메서드와 this (0) | 2022.12.25 |