JS STUDY - Symbol

👊0👊·2020년 2월 9일
0

es6 스터디

목록 보기
7/8

new type : 7

태초에 6개의 타입이 있었다.

  • Undefined
  • Null
  • Boolean
  • Number
  • String
  • Object

이 타입들은 어떤 값들의 집합이다. 모두 유한한 집합이다.(Object는 제외)
Boolean은 true, false를 가지고 있다.
Number, String은 좀 더 많은 값을 가지고 있다.
(ES6에서 Number의 갯수는 18,437,736,874,454,810,627개이다)
(String은 (2144,115,188,075,855,872 − 1) ÷ 65,535 개이다.)

다만 Object는 고유하면서 무한하다.

심볼은 문자열은 아니고, 그렇다고 객체도 아니다.
완전 새로운 7번째 타입이다.

Symbol != String
Symbol != Object

심볼의 특징

심볼은 es6의 추가된 원시타입이다.
심볼은 privagte한 프로퍼티를 만들기 위해 제작되었다고 한다.
아래는 es2020 명세의 심볼소개 문장이다.

심볼 타입은 오브젝트 프로퍼티의 키로 사용될 수 있는 모든 논-스트링 값들의 집합이다.
각 심볼 값들은 유일하고 불변할 수 있다.
각 심볼 값들은 변치않고 undefined나 문자열 값 중 하나가 [[Description]]로 불리는 관련된 값을 불변으로 갖고 있는다.

정리하자면 다음과 같은 특징이 있다.

  • 오브젝트의 키
  • 유일
  • 불변
  • 유일 => 무한

하지만 처음 의도와는 다르게 다운그레이드 되었다. 예를 들어, Object.getOwnPropertySymbols등으로 심볼을 찾아볼 수 있다.

이제 심볼은 고유한 값으로 사용된다. 프로퍼티 간의 이름 충돌을 피하기위한 용도로만 사용된다.
하지만 그럼에도 심볼은 유용하다.

심볼의 생성

기억하세요 인자는 단순한 설명입니다.

  1. Symbol();
  2. Symbol().for();
  3. Symbol.iterator

var ob = {};
var a = Symbol.for('key');
var b = Symbol.for('key');

console.log(a)
// Symbol(key)
console.log(b)
//Symbol(key)
console.log(a === b)
//true
console.log(a == b)
//true
ob[a] = 20;
// 20
ob[b]
// 20
ob[a] === ob[b];
// true
Symbol.keyFor(a)
// "key"
Symbol.keyFor(b)
// "key"

심볼의 유용성

1. 유일한 값 => 로그레벨

로깅 라이브러리를 만들어보자.
logger.levels.DEBUG, logger.levels.INFO, logger.levels.WARN 등과 같은 다양한 로그레벨이 필요하다.
ES5에선 주로 String이나 Number를 이용했을 것이다.
logger.levels.DEBUG === 'debug' 또는logger.levels.DEBUG === 10)
하지만 이 코드는 유일한 값이 아니라 이상적이지 않다. 하지만 심볼은 그렇지 않다!
아래와 같이 단순하게 해보자.

log.levels = {
    DEBUG: Symbol('debug'),
    INFO: Symbol('info'),
    WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');

2. 오브젝트 안에다 메타데이터 값을 넣기

실제 객체에 부차적인 커스텀 메타데이터 프로퍼티를 저장하여 사용할 수 있다.
이건 열거될 수 없는 보조 층이라 생각하라.(Object.getOwnproperties로 열거할 수 있긴하다.)
이제 우리의 믿을 수 있는 Collection class를 만들어보자. 그리고 숨겨져야 되는 size라는 참조를 추가하자.
심볼로 간단하게 만들 수 있다.

var size = Symbol('size');
class Collection {
    constructor() {
        this[size] = 0;
    }

    add(item) {
        this[this[size]] = item;
        this[size]++;
    }

    static sizeOf(instance) {
        return instance[size];
    }

}

var x = new Collection();
assert(Collection.sizeOf(x) === 0);
x.add('foo');
assert(Collection.sizeOf(x) === 1);
assert.deepEqual(Object.keys(x), ['0']);
assert.deepEqual(Object.getOwnPropertyNames(x), ['0']);
assert.deepEqual(Object.getOwnPropertySymbols(x), [size]);

유일한 값

dom 엘리먼트를 스크린 위에 움직이게 js를 이용해서 움직여보자.
dom 엘리먼트를 조작할 일이 있다고하자.

Well-known Symbol


위의 사진은 잘 알려진 심볼들의 표이다. 하지만 이렇게 보면 감이 안오니 분류를 해보자.
또한 위 심볼들은 대부분 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }이다.

정규표현식

  • Symbol.match
  • Symbol.replace
  • Symbol.search
  • Symbol.split
var ob = {
    [Symbol.match]: (v) => (v.match(/[\d]+/g)),
    [Symbol.replace]: (v) => (v.replace(/[\d]+/g, '')),
    [Symbol.search]: (v) => (v.search(/[\d]+/g)),
    [Symbol.split]: (v) => (v.split(',')),
}

console.log('asdf123afe'.match(ob));
// ["123"]

console.log('asdf123afe'.replace(ob));
// asdfafe

console.log('asdf123afe'.search(ob));
// 4

console.log('asdf,123,afe'.split(ob));
// ["asdf", "123", "afe"]

그 외 객체를 설정하기 위한 심볼들

심볼은 내부 프라이빗 프로퍼티를 설정할 수 있다는 것은 외부로 노출되지 않은 설정을 할 수 있다는 말과 같다.
즉 여러가지 설정을 심볼로 할 수 있다.

Symbol.isConcatSpreadable

Symbol.toPrimitive

Symbol.toStringTag

참고자료

심볼

profile
ㅎㅎ

0개의 댓글