NATIVE

settings_applicationsObject

NATIVE

Editing
  • account_tree
  • bug_report

ObjectSymbol

Symbol 객체는 "symbol" 유형의 원시 데이터를 유일한 값으로 생성하여 객체의 프로퍼티로 사용한다.

설명

개요

ECMAScript 6(이하 ES6)에서 Symbol 객체가 추가되었다. Symbol() 함수에 의해서 생성된 데이터는 "symbol" 유형을 갖는 원시 타입 데이터로서 유일성을 갖는다.

새로운 데이터 타입의 추가

ECMAScript는 string, number, boolean, undefined, null 이라는 원시 데이터 타입이 존재한다. 여기에 ES6에서는 symbol 이라는 새로운 원시 데이터 타입을 추가했다. 그리고 이 데이터 타입은 한 번 생성되면 변경이 불가능하다는 특징을 가지고 있고 생성된 모든 심벌(symbol)은 유일한 값이 된다.

심벌(symbol) 데이터의 생성

symbol은 다른 원시 타입(string, number, boolean) 처럼 래퍼(wrapper) 객체(각각 String, Number, Boolean)를 가지고 있지 않다. 하지만 프로토타입 메소드가 존재하듯이 객체처럼 다루어진다. 하지만 일반 객체와는 다른 성격을 갖고 있는 특별한 객체라고 한다. 이러한 특징으로 생성자 함수를 지원하나 new 연산자 사용을 금하며 Symbol() 이라는 함수 호출을 통해서만 생성이 가능하다.

심벌을 생성할 때는 Symbol() 함수에게 디스크립션(description)을 지정할 수 있다. 이 디스크립션은 값이 아니라 심벌에 대한 설명이라 할 수 있고 디버깅 용도로 사용되어진다.

const symbol = Symbol("my symbol");

심벌을 생성하는 몇 가지 방법은 Constructor를 참고하기 바란다.

심벌(symbol)의 사용

심벌은 고유성을 가지므로 중복된 프로퍼티를 생성하지 않도록 하는 목적으로 사용된다. 그리고 심벌로 정의된 프로퍼티는 닷(.)으로 접근하지 못하고 키(key)로만 접근이 가능하다.

let myProp = Symbol();

let myObj = {};
myObj[myProp] = "Hello";

console.log(myObj[myProp]); // "Hello"

심벌(symbol)의 가치

아무리 새롭게 추가된 것이라도 그 가치가 높지 않다면 무용지물이 될 소지가 크다. 심벌은 간편하게 유일한 값을 생성하는 유일무이한 수단이다. 그것만으로도 충분한 가치가 있다. 그런데 왜 유일한 값에 집착할까? 그냥 조심해서 중복되지 않는 값을 사용하면 될 일이라고 생각할 수도 있다. 간단한 코드나 시스템에서는 그럴수는 있겠지만 규모가 큰 코드에서는 이게 쉬운 일이 아니다. 특히 클래스(class) 기반의 코드에서는 클래스 상속이 매우 흔한 일이다. 안타깝게도 ECMAScript는 최근 클래스 문법을 지원하지만 다른 언어의 클래스처럼 객체 멤버를 은닉하는 것을 공식적으로 지원하지 않는다. 객체 멤버를 은닉하는 것은 몇 가지 이유가 있겠지만 무엇보다도 오염에 대한 방지가 큰 이유이다.

다음 샘플 코드는 부모 클래스를 상속 받아 자식 클래스에서 부모 클래스의 멤버의 값을 변경하는 것을 확인할 수 있다.

의도된 것이라면 문제될 게 없지만 부모 클래스를 확인하지 않고 구현했다면 치명적인 문제가 발생될 수도 있다. 그래서 ECMAScript 2019에서 새롭게 도입한 Private Class Fields를 통해 혹시 안전 장치가 있는지를 확인해 보았다. 필드앞에 #을 붙이면 프라이빗 멤버(private member)가 된다.

단지 접근할 수 없다는 의미의 undefined로 처리되지만 접근 자체는 막지 않고 있다. 그리고 부모 클래스에서 보호될 코드상의 parentName 필드는 자식 클래스에서 오염되었다. 이러한 결과는 조심하지 않으면 문제가 발생할 수 있다는 것을 의미한다. 그렇다면 오염을 막을 방법은 전혀 없는 것인가? 바로 여기서 심벌은 중요한 역할을 한다. 다음 코드는 오염되지 말아야할 필드를 심벌로 정의했다.

상수(constant)로 심벌을 사용했으니 하위 클래스에서 같은 상수를 선언하면 에러가 발생할 것이다.  따라서 오염은 막았으나 아쉽게도 은닉은 되지 않는다.

클래스 필드 은닉은 다양한 방식으로 개발자에 의해 시도되고 있다. 현재 섹션은 심벌에 대한 주제를 다루므로 심벌의 가치에 대한 설명을 하는 것으로 마무리하고자 한다.

하위 트리 탐색

  • Constructor

    Symbol 객체는 생성자 함수가 존재하며 호출만으로 생성이 가능하다. 또한 심벌을 생성하는 몇 가지 방법이 더 있으므로 아래의 설명과 문법을 참고하기 바란다.

    • Symbol()

      유일한 새로운 심벌을 생성하여 반환한다. new 연산자는 사용하지 않는다.

  • [[Prototype]]

    • Properties

      • description

        현재 심벌(symbol)에 대한 설명을 조회한다. 설명이 없는 경우에는 undefined를 갖는다.

    • Methods

      • @@toPrimitive

        현재 심벌의 값을 반환한다.

      • toString()

        현재 심벌(symbol)을 나타내는 문자열을 반환한다.

      • valueOf()

        현재 심벌(symbol)의 원시값을 반환한다.

  • Static

    정적(static) 멤버를 의미하며 인스턴스(instance)에 상속되어 사용할 수 없고 오로지 하위를 포함하여 객체(object) 또는 인터페이스(interface) 자신에서 해당 멤버에 접근이 가능하다. 

    • Properties

      • asyncIterator

        잘 알려진 심벌(well-know symbol)을 나타낸다. 비동기 반복자를 반환하는 메소드에 대한 접근 키를 나타내며 이 심벌을 키로 사용하는 객체는 비동기 반복자를 반환하는 메소드가 구현되어 있어야 한다.

      • hasInstance

        잘 알려진 심벌(well-know symbol)을 나타낸다. instanceof 연산자에 대한 접근 키를 나타내며 이 심벌을 키로 사용하여 instanceof 연산자를 재정의할 수 있다.

      • isConcatSpreadable

        잘 알려진 심벌(well-know symbol)을 나타낸다.Array.prototype.concat() 메소드는 연결을 위해 지정된 객체에서 이 심벌을 조회하여 해당 객체를 평면화해야 하는지 확인할 수 있다. 지정된 배열 및 유사 배열 객체에서 이 심벌을 키로 가진 프로퍼티로 통해 평면화 여부를 설정할 수 있다.

      • iterator

        잘 알려진 심벌(well-know symbol)을 나타낸다. 반복 가능한 반복자를 반환하는 메소드에 대한 접근 키를 나타내며 이 심벌을 키로 사용하는 객체는 반복 가능한 반복자를 반환하는 메소드가 구현되어 있어야 한다.

      • match

        잘 알려진 심벌(well-know symbol)을 나타낸다. String.prototype.match() 메소드의 첫 번째 인수에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드를 가진 객체가 지정되었다면 해당 메소드의 반환값을 사용한다.

        또한 이 심벌은 인수로 지정된 정규식을 정규식으로 처리해야 하는지의 여부를 설정할 수도 있다.

      • matchAll

        잘 알려진 심벌(well-know symbol)을 나타낸다. String.prototype.matchAll() 메소드의 첫 번째 인수에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드를 가진 객체가 지정되었다면 해당 메소드의 반환값을 사용한다.

        또한 이 심벌은 지정될 정규식에서 이 심벌을 사용한 키로 호출되는 메소드로 특정 문자열을 지정하여 정규식을 적용할 수 있다.

      • replace

        잘 알려진 심벌(well-know symbol)을 나타낸다. String.prototype.replace() 메소드의 첫 번째 인수에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드를 가진 객체가 지정되었다면 해당 메소드의 반환값을 사용한다.

      • search

        잘 알려진 심벌(well-know symbol)을 나타낸다. String.prototype.search() 메소드의 첫 번째 인수에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드를 가진 객체가 지정되었다면 해당 메소드의 반환값을 사용한다.

      • species

        잘 알려진 심벌(well-know symbol)을 나타낸다. 객체의 인스턴스를 생성할 때 객체내에 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드에서 생성자를 반환받아 생성자로 사용한다.

      • split

        잘 알려진 심벌(well-know symbol)을 나타낸다. String.prototype.split() 메소드의 첫 번째 인수에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드를 가진 객체가 지정되었다면 해당 메소드의 반환값을 사용한다.

      • toPrimitive

        잘 알려진 심벌(well-know symbol)을 나타낸다. 객체의 valueOf(), toString() 메소드가 동작되기 전에 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드가 지정되었다면 해당 메소드의 반환값을 사용한다.

      • toStringTag

        잘 알려진 심벌(well-know symbol)을 나타낸다. 객체 유형을 문자열로 나타내는 Object.prototype.toString() 메소드가 this 값에서 이 심벌을 검색하여 이 심벌을 키로 사용하는 메소드가 지정되었다면 해당 메소드의 반환값을 사용한다.

      • unscopables

        잘 알려진 심벌(well-know symbol)을 나타낸다. with 구문 스코프(scope)내에서 바인딩되면 안되는 프로퍼티를 이 심벌을 키로 가진 객체에서 찾는다.

    • Methods

      • for()

        런타임 와이드 심볼 레지스트리(runtime-wide symbol registry)에서 지정된 키로 존재하는 심볼을 찾아 반환한다. 없으면 전역 심볼 레지시트리(global symbol registry)에 해당 키로 새로운 심볼을 생성한다.

      • keyFor()

        지정된 심벌(symbol)을 사용하여 전역 심벌 레지스터리(global symbol registry)에서 해당 심벌의 키를 검색한다.

지원 웹브라우저