Growth from the root - Vanilla JavaScript - 심볼형

이형준·2023년 4월 7일
0
post-thumbnail

심볼형

📃 자바스크립트는 객체의 키로 오직 문자형과, 심볼형만 허용함.



심볼 ?

📃 심볼은 유일한 식별자(unique identifer)를 만들고 싶을 떄 사용함, "Symbole()"을 사용하면 심볼을 사용할 수 있음.

// id는 새로운 심볼이 됩니다.
let id = Symbole();

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

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

// 심볼은 유일성이 보장되는 자료형임, 설명이 동일한 심볼을 여러개 만들어도 각 심볼값은 다름.
alert(id1 == id2); // false



'숨김' 프로퍼티

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

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

let id = Symbol("id");

user[id] = 1;

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

✏️ 서드파티 코드에서 가지고 온 user 라는 객체가 여러개 있고, user를 이용해 어떤 작업을 해야하는 상황임.
그런데 문자열 "id"를 키로 사용해도 되는데 굳이 Symbol("id")를 왜 써 ?
✅ user 는 서드파티 코드에서 가져왔기 때문에 함부로 프로퍼티를 추가할 수 없음, 그런데 심볼은 서드파티 코드에서 접근할 수 없기 때문에 서드파티 모르게 식별자를 부여할 수 있음

📃 라이브러리에서 user를 식별해야 할 상황일 때는 ?

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

user[id] = "제3 스크립트 id 값";

✏️ 위와 같이 "Symbol("id")"를 이용해 전용 식별자를 만들어 사용함, 심볼은 유일성이 보장되므로 충돌하지 않음.



Symbole in a literal

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

let id = Symbol("id");

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

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



Symbole은 for ... in 에 ❌

📃 키가 심볼인 프로퍼티는 for ... in 반복문에서 배제

let id = Symbol("id");
let user = {
  name: "John",
  age: 30,
  [id]: 123
};

for (let key in user) alert(key); // name과 age만 출력되고, 심볼은 출력되지 않습니다.

// 심볼로 직접 접근하면 잘 작동합니다.
alert( "직접 접근한 값: " + user[id] );



전역 심볼

📃 심볼은 이름이 같더라도 모두 별개로 취급됨, 그런데 이름이 같은 심볼이 같은 개체를 가르키길 원하는 경우도 있음.
✅ 이럴 때 쓰는 게 전역 심볼 레지스트리(global symbol registry)
: 전역 심볼 레지스트리 안에 심볼을 만들고 해당 심볼에 접근하면, 이름이 같은 경우 항상 동일한 심볼을 반환.
✏️ 레지스트리 안에 있는 심볼을 읽거나, 생성하려면 Symbol.for(key)를 사용.

// 전역 레지스트리에서 심볼을 읽습니다.
let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.

// 동일한 이름을 이용해 심볼을 다시 읽습니다(좀 더 멀리 떨어진 코드에서도 가능합니다).
let idAgain = Symbol.for("id");

// 두 심볼은 같습니다.
alert( id === idAgain ); // true



Symbol.keyFor

📃 전역심볼을 찾을 때 사용되는 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

✏️Symbol.keyFor는 전역 심볼 레지스트리를 뒤져서 해당 심볼의 이름을 얻어냄, 검색 범위가 전역 심볼 레지스트리이기 때문에 전역 심볼이 아닌 심볼에는 사용할 수 없음.

전역 심볼이 아닌 인자가 넘어오면 Symbol.keyFor는 undefined를 반환.

전역 심볼이 아닌 모든 심볼은 description 프로퍼티가 있음, 일반 심볼에서 이름을 얻고 싶으면 description 프로퍼티를 사용하면 됩니다.

let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name, 전역 심볼
alert( Symbol.keyFor(localSymbol) ); // undefined, 전역 심볼이 아님

alert( localSymbol.description ); // name
profile
프론트엔드 개발자 이형준입니다.

0개의 댓글