설모의 기록

Symbol 본문

언어/TypeScript

Symbol

HA_Kwon 2018. 1. 3. 20:32

ES5 에서 원시 타입(primitive type)은 6가지가 있었죠. 바로 boolean, number, string, null, undefined, object 입니다. 

이제 ES6 에서부터 Symbol 이라는 타입이 하나 추가되었습니다. 간단한 예제는 아래와 같습니다. 언뜻 보면 'String 아니야?' 라고 할 수 있겠지만 String 타입이 아니라 Symbol 타입입니다.

  Symbol 타입을 사용하는 이유는 변수나 메소드같은 것들의 이름을 충돌 없이 프로그래밍 하기 위해서입니다. 간단한 예를 들어보겠습니다. Array.isArray() 메소드가 생기기 이전, 필요에 의해 string 을 반환하는 Array.isArray() 메소드를 구현해 코드에 추가했다고 가정해보겠습니다. 그 이후 boolean 값을 반환하는 Array.isArray() 메소드가 추가되었습니다. 그렇다면 새로 생긴 메소드에 의해 원래 저희가 구현했던 Array.isArray() 메소드는 덮어씌워지게 됩니다. 그동안 isArray() 가 string 을 반환하는 줄 알고 나머지 코드에서 사용했었는데 갑자기 boolean 을 반환해 구현해놨던 코드들이 꼬이게 되는거죠. (물론 네임스페이스 패턴을 잘 사용하면 문제 없을 것입니다. )

  이런 경우에 사용하는 것이 Symbol 입니다. 심볼은 매번 새 심볼을 생성하기 때문입니다. 아래의 예제를 보면 sym1 과 sym2 는 같지 않다는 결과를 얻을 수 있습니다.


  또한 객체에서 프로퍼티로 심볼을 사용하게 되면 프로퍼티를 은닉할 수도 있습니다.

  위의 예제에서는 [symbol] 이라는 프로퍼티가 존재하지만 for-in 문으로 key 값을 출력해보면 출력되지 않습니다. 그렇다고해서 완전히 은닉하는 것은 아닙니다. Object.getOwnPropertySymbols() 메소드를 사용하면 객체의 프로퍼티 중 심볼인 것들을 배열로 반환합니다.




ES6 에는 잘 알려진 built-in symbol 들이 있습니다. 

  • Symbol.hasInstance : 이 메소드는 생성자 객체가 검사하려는 객체를 생성자의 객체로 인식하는지를 결정합니다. instanceof 오퍼레이터가 커스텀됩니다.

이런식으로 instanceof operator 의 기능을 커스터마이징 할 수 있습니다. 따라서 위의 예제의 마지막 줄의 console.log(); 는 true 르 출력합니다.


  • Symbol.isConcatSpreadable : 이 메소드는 배열과 배열과 비슷한 객체에서 동작합니다. 
        - 배엻 : 이 메소드를 false 로 설정하면 배열을 합칠 때 펼치는 것을 피합니다. default 는 펼쳐집니다.
        - 객체 : 이 메소드를 true 로 설정하면 객체의 프로퍼티들이 펼쳐지도록 강제합니다.  default 는 펼쳐지지 않습니다.
    아래의 예제를 보시면 이해될거예요 :)

위의 예제들은 이해하기 쉽도록 자바스크립트 기준으로 구현한 코드입니다. 타입스크립트에서 실행하면 타입이 다른 배열을 합치려 한다, [Symbol.isConcatSpreadable] 타입은 number parameter 에 할당되지 않는다 라는 에러들이 발생할거예요! 객체에서는 배열과 같이 키 값이 숫자로 된 프로퍼티들만 합쳐집니다.


  • Symbol.iterator : 객체가 반복될 필요가 있을 때 사용하며 인자를 받지 않고 반복된 값을 반환하는 iterator 를 반환하는 함수를 제공합니다. (일반적으로 iterator 는 배열이나 객체를 순회할 때 유용하게 쓰입니다. )


  • Symbol.match : String.prototype.startWith() , String.prototype.endsWith() , String.prototype.includes() 메소드들은 첫 번째 인자가 정규 표현식이 있는지 확인하고 실행됩니다. 이 때, Symbol.match property 값을 false 로 바꿔주면 정규 표현식 객체로 사용되지 않을 것입니다. 아래 예제를 살펴보겠습니다.

위의 코드는 자바스크립트 코드입니다.

첫 번째 예제에서는 String.prototype.startWith() 의 인자로 정규표현식인 /bar/ 를 넣었습니다. 따라서 TypeError 가 발생합니다.

두 번째 예제에서는 string 타입인 reg 변수의 Symbol.match 프로퍼티 값을 false 로 바꿔준 후, 첫 번째 예제에서와 같이 실행하면 원했던 결과인 true 를 얻을 수 있습니다. Symbol.match 를 false 로 바꿔줬기 때문에 인자로 들어오는 값이 정규식 형태여도 정규식으로 받아들이지 않습니다.



  • Symbol.species : 파생된 것의 객체를 만드는데 쓰이는 함수를 값으로 가지는 프로퍼티입니다. 

위의 예제에서 보면 원래는 a 의 생성자를 찍어보면 MyArray 여야 하지만 Symbol.species 의 함수에서 Array 를 반환하도록 구현했기 때문에 맨 밑줄에서 true 가 반환됩니다.



이상으로 es6의 Symbol 타입에 대해 알아보았습니다 :)

'언어 > TypeScript' 카테고리의 다른 글

Promise  (0) 2018.01.02
Classes Emit  (0) 2017.12.28
Classes Super  (0) 2017.12.28
TypeScript Class  (0) 2017.12.28
TypeScript Index Signature  (0) 2017.12.28
Comments