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