# 심볼형

자바 스크립트 객체 프로퍼티의 자료형 : 문자형, 심볼형

# 심볼 Symbol

Symbol() 유일한 식별자를 만들때 사용함.

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

# 심볼이름 붙이기

  • 디버깅시 유용함.
// 심볼 id에는 "id"라는 설명이 붙습니다.
let id = Symbol("id");
1
2
  • 이름을 붙여도 심볼이 반환하는 값은 항상 다르다.
let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false
1
2
3
4

# 심볼의 자동형변환

  • 심볼의 암시적 형변환 X
let id = Symbol("id");
alert(id); // TypeError: Cannot convert a Symbol value to a string
1
2
  • 자바스크립트: 문자형으로 암시적 형변환이 비교적 자유로움

-> alert 함수가 거의 모든 값을 인자로 받을 수 있다.

  • 심볼을 alert 로 출력하는 방법
    • .toString() 메서드 호출
    • symbo.description 프로퍼티 사용
    let id = Symbol("id");
    alert(id.toString()); // Symbol(id)가 얼럿 창에 출력됨
    alert(id.description); // id
    
    1
    2
    3

# 심볼을 이용한 숨김 프로퍼티

숨김 프로퍼티

  • 외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없는 프로퍼티
  • 서드 파티 코드는 일반적으로 접근할 수 없다.
  • 심볼을 사용하면 서드파티 모르게 user 에 식별자를 부여할 수 있다.
let user = { // 서드파티 코드에서 가져온 객체
  name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] ); // 심볼을 키로 사용해 데이터에 접근할 수 있습니다.
1
2
3
4
5
6
7
8
9

만약 제3의 스크립트가 우리 스크립트와 동일하게 문자열 "id"를 이용해 식별자를 만들었다면

let user = { name: "John" };

// 문자열 "id"를 사용해 식별자를 만들었습니다.
user.id = "스크립트 id 값";

user.id = "제3 스크립트 id 값"
// 의도치 않게 값이 덮어 쓰여서 우리가 만든 식별자는 무의미해집니다.
1
2
3
4
5
6
7

사실상 심볼을 완전히 숨기는 방법은 없다.

  • Object.getOwnPropertySymbols(obj) 모든 심볼을 볼 수 있다.
  • Reflect.ownKeys(obj) 심볼형 키를 포함한 객체의 모든 키를 반환한다.

# 객체 리터럴에서의 심볼

let id = Symbol("id");

let user = {
  name: "John",
  [id]: 123 // "id": 123은 안됨
};
1
2
3
4
5
6

# 심볼은 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] );
1
2
3
4
5
6
7
8
9
10
11

# Object.assign 은 키가 심볼인 프로퍼티도 복사

let id = Symbol("id");
let user = {
  [id]: 123
};

let clone = Object.assign({}, user);

alert( clone[id] ); // 123
1
2
3
4
5
6
7
8

# 전역 심볼 레지스트리 (global symbol registry)

전역 심볼 레지스트리 안에 심볼을 만들고 해당 심볼에 접근하면 항상 동일한 심볼을 반환해준다.

Symbol.for(key) 로 접근 / 생성

  • 호출
    • 조건에 맞는 심볼 검사
    • 없다면 새로운 Symbol(key) 를 만들고 레지스트리 안에 저장함.
    • 이름이 key 인 심볼 반환
// 전역 레지스트리에서 심볼을 읽습니다.
let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.

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

// 두 심볼은 같습니다.
alert( id === idAgain ); // true
1
2
3
4
5
6
7
8

# 전역 심볼

  • 전역 심볼 레지스트리 안에 있는 심볼
  • 어플리케이션에서 광범위 하게 사용해야 하는 심볼

# Symbol.keyFor(sym)

전역 심볼 레지스트리에서 심볼으로 이름을 얻는 메서드

  • 찾지 못하면 undefined 반환

  • Symbol.for(key) 와 반대됨

// 이름을 이용해 심볼을 찾음
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");

// 심볼을 이용해 이름을 얻음
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id
1
2
3
4
5
6
7
  • 일반 심볼에서 이름을 얻고 싶을 땐 description 프로퍼티를 사용한다.
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

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

alert( localSymbol.description ); // name
1
2
3
4
5
6
7

# 시스템 심볼

자바스크립트 내부에서 사용되는 심볼

  • 내장 메서드 등의 기본 동작을 변경할 수 있다.
  • iterable 객체 -> Symbol.iterator
  • 객체를 원시형으로 변환 -> Symbol.toPrimitive

# 잘 알려진 심볼 well-known-symbols

  • Symbol.hasInstance
  • Symbol.isConcatSpreadable
  • Symbol.iterator
  • Symbol.toPrimitive
  • etc

# 더 보면 좋은 글