사용자 도구

사이트 도구


typescript:symbol

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

다음 판
이전 판
typescript:symbol [2019/07/29 15:45] – 만듦 taekgutypescript:symbol [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 ====== Symbol ====== ====== Symbol ======
 ===== Introduction ===== ===== Introduction =====
-ECMAScript 2015에서부터 ''symbol''은 ''number''와 ''string''과 같은 기본 데이타 타입(primitive data type)이다.+ECMAScript 2015에서부터 ''symbol''은 ''number''와 ''string''과 같은 기본 데이타 타입(primitive data type)이 되었다.
  
 ''symbol''값들은 ''Symbol''이라는 생성자를 호출하여 생성된다. ''symbol''값들은 ''Symbol''이라는 생성자를 호출하여 생성된다.
줄 10: 줄 10:
 </code> </code>
  
 +
 +Symbol은 변경 불가능하며 고유합니다.
 +
 +<code javascript>
 +let sym2 = Symbol("key");
 +let sym3 = Symbol("key");
 +sym2 === sym3; // false, symbols are unique
 +</code>
 +
 +string과 마찬가지로 symbol을 객체 프로퍼티의 키로 사용할 수 있습니다.
 +
 +<code javascript>
 +let sym = Symbol();
 +let obj = {
 +    [sym]: "value"
 +};
 + 
 +console.log(obj[sym]); // "value"
 +</code>
 +
 +Symbol을 계산된 프로퍼티 선언과 결합하여 객체 프로퍼티와 클래스 멤버를 선언할 수도 있습니다.
 +
 +<code javascript>
 +const getClassNameSymbol = Symbol();
 +class C {
 +    [getClassNameSymbol](){
 +       return "C";
 +    }
 +}
 +let c = new C();
 +let className = c[getClassNameSymbol](); // "C"
 +</code>
 +
 +==== 잘 알려진 Symbol ====
 +
 +사용자 정의 Symbol 외에도 잘 알려진 내장 Symbol이 있습니다. 내장 Symbol는 언어 내부 동작을 나타내는 데 사용됩니다.
 +
 +다음은 잘 알려진 Symbol 목록입니다.
 +
 +''Symbol.hasInstance''
 +생성자 객체가 생성자의 인스턴스 중 하나로서 객체를 인식하는지 여부를 결정하는 메서드입니다. instanceof 연산자의 의미에 의해 호출됩니다.
 +
 +''Symbol.isConcatSpreadable''
 +객체가 Array.prototype.concat에 의해 배열 요소로 병합되어야 함을 나타내는 부울 값입니다.
 +
 +''Symbol.iterator''
 +객체의 기본 반복자를 반환하는 메서드입니다. for-of 구문의 의미에 의해 호출됩니다.
 +
 +''Symbol.match''
 +문자열과 비교하는 정규 표현식 메서드입니다. String.prototype.match 메서드에 의해 호출됩니다.
 +
 +''Symbol.replace''
 +일치하는 문자열의 부분 문자열을 대체하는 정규 표현식 메서드입니다. String.prototype.replace 메서드에 의해 호출됩니다.
 +
 +''Symbol.search''
 +일치하는 문자열 내에서 인덱스를 반환하는 정규 표현식 메서드입니다. String.prototype.search 메서드에 의해 호출됩니다.
 +
 +''Symbol.species''
 +파생된 객체를 만드는 데 사용되는 생성자 함수의 함수값을 갖는 프로퍼티입니다.
 +
 +''Symbol.split''
 +일치하는 인덱스에서 문자열을 분할하는 정규 표현식 메서드입니다. String.prototype.split 메서드에 의해 호출됩니다.
 +
 +''Symbol.toPrimitive''
 +객체에 대응하는 Primitive로 변환하는 메소드입니다. ToPrimitive 추상 동작에 의해 호출됩니다.
 +
 +''Symbol.toStringTag''
 +객체의 기본 문자열 Tag를 만드는데 사용되는 String 값입니다. 내장 메소드 Object.prototype.toString에 의해 호출됩니다.
 +
 +''Symbol.unscopables''
 +자신의 프로퍼티 명을 가지는 객체는 관련된 객체의 ‘with’ 환경 바인딩에서 제외되는 속성 이름입니다.
 +
 +==== Symbol사용 ====
 +(Javascript에서 가져옴. Typescript확인필요)
 +=== Symbols in a literal ===
 +객체 리터럴 {...}을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 합니다.
 +<code javascript>
 +let id = Symbol("id");
 +let user = {
 +  name: "John",
 +  [id]: 123 // "id": 123은 안됨
 +};
 +</code>
 +=== 심볼은 for…in 에서 배제됩니다 ===
 +키가 심볼인 프로퍼티는 for..in 반복문에서 배제됩니다.
 +<code javascript>
 +let id = Symbol("id");
 +let user = {
 +  name: "John",
 +  age: 30,
 +  [id]: 123
 +};
 +
 +for (let key in user) alert(key); // name과 age만 출력되고, 심볼은 출력되지 않습니다.
 +
 +// 심볼로 직접 접근하면 잘 작동합니다.
 +alert( "직접 접근한 값: " + user[id] );
 +</code>
 +**Object.keys(user)**에서도 키가 심볼인 프로퍼티는 배제됩니다. '심볼형 프로퍼티 숨기기(hiding symbolic property)'라 불리는 이런 원칙 덕분에 외부 스크립트나 라이브러리는 심볼형 키를 가진 프로퍼티에 접근하지 못합니다.
 +
 +그런데 Object.assign은 키가 심볼인 프로퍼티를 배제하지 않고 객체 내 모든 프로퍼티를 복사합니다.
 +<code javascript>
 +let id = Symbol("id");
 +let user = {
 +  [id]: 123
 +};
 +
 +let clone = Object.assign({}, user);
 +
 +alert( clone[id] ); // 123
 +</code>
 +뭔가 모순이 있는 것 같아 보이지만, 이는 의도적으로 설계된 것입니다. 객체를 복사하거나 병합할 때, 대개 id 같은 심볼을 포함한 프로퍼티 전부를 사용하고 싶어 할 것이라는 생각에서 이렇게 설계되었습니다.
 +=== 전역 심볼 ===
 +앞서 살펴본 것처럼, 심볼은 이름이 같더라도 모두 별개로 취급됩니다. 그런데 이름이 같은 심볼이 같은 개체를 가리키길 원하는 경우도 가끔 있습니다. 애플리케이션 곳곳에서 심볼 "id"를 이용해 특정 프로퍼티에 접근해야 한다고 가정해 봅시다.
 +
 +전역 심볼 레지스트리(global symbol registry) 는 이런 경우를 위해 만들어졌습니다. 전역 심볼 레지스트리 안에 심볼을 만들고 해당 심볼에 접근하면, 이름이 같은 경우 항상 동일한 심볼을 반환해줍니다.
 +
 +레지스트리 안에 있는 심볼을 읽거나, 새로운 심볼을 생성하려면 Symbol.for(key)를 사용하면 됩니다.
 +
 +이 메서드를 호출하면 이름이 key인 심볼을 반환합니다. 조건에 맞는 심볼이 레지스트리 안에 없으면 새로운 심볼 Symbol(key)을 만들고 레지스트리 안에 저장합니다.
 +<code script>
 +// 전역 레지스트리에서 심볼을 읽습니다.
 +let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.
 +
 +// 동일한 이름을 이용해 심볼을 다시 읽습니다(좀 더 멀리 떨어진 코드에서도 가능합니다).
 +let idAgain = Symbol.for("id");
 +
 +// 두 심볼은 같습니다.
 +alert( id === idAgain ); // true
 +</code>
 +전역 심볼 레지스트리 안에 있는 심볼은 전역 심볼이라고 불립니다. 애플리케이션에서 광범위하게 사용해야 하는 심볼이라면 전역 심볼을 사용하세요.
 +=== Symbol.keyFor ===
 +전역 심볼을 찾을 때 사용되는 Symbol.for(key)에 반대되는 메서드도 있습니다. Symbol.keyFor(sym)를 사용하면 이름을 얻을 수 있습니다.
 +<code javascript>
 +// 이름을 이용해 심볼을 찾음
 +let sym = Symbol.for("name");
 +let sym2 = Symbol.for("id");
 +
 +// 심볼을 이용해 이름을 얻음
 +alert( Symbol.keyFor(sym) ); // name
 +alert( Symbol.keyFor(sym2) ); // id
 +</code>
 +Symbol.keyFor는 전역 심볼 레지스트리를 뒤져서 해당 심볼의 이름을 얻어냅니다. 검색 범위가 전역 심볼 레지스트리이기 때문에 전역 심볼이 아닌 심볼에는 사용할 수 없습니다. 전역 심볼이 아닌 인자가 넘어오면 Symbol.keyFor는 undefined를 반환합니다.
 +
 +전역 심볼이 아닌 모든 심볼은 description 프로퍼티가 있습니다. 일반 심볼에서 이름을 얻고 싶으면 description 프로퍼티를 사용하면 됩니다.
 +<code javascript>
 +let globalSymbol = Symbol.for("name");
 +let localSymbol = Symbol("name");
 +
 +alert( Symbol.keyFor(globalSymbol) ); // name, 전역 심볼
 +alert( Symbol.keyFor(localSymbol) ); // undefined, 전역 심볼이 아님
 +
 +alert( localSymbol.description ); // name
 +</code>
 +=== 시스템 심볼 ===
 +'시스템 심볼(system symbol)'은 자바스크립트 내부에서 사용되는 심볼입니다. 시스템 심볼을 활용하면 객체를 미세 조정할 수 있습니다.
 +
 +명세서 내의 표, 잘 알려진 심볼(well-known symbols)에서 어떤 시스템 심볼이 있는지 살펴보세요.
 +  * Symbol.hasInstance
 +  * Symbol.isConcatSpreadable
 +  * Symbol.iterator
 +  * Symbol.toPrimitive
 +  * 기타 등등
  
  
typescript/symbol.1564415153.txt.gz · 마지막으로 수정됨: 2025/04/15 10:05 (바깥 편집)