태초에 6개의 타입이 있었다.
이 타입들은 어떤 값들의 집합이다. 모두 유한한 집합이다.(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등으로 심볼을 찾아볼 수 있다.
이제 심볼은 고유한 값으로 사용된다. 프로퍼티 간의 이름 충돌을 피하기위한 용도로만 사용된다.
하지만 그럼에도 심볼은 유용하다.
기억하세요 인자는 단순한 설명입니다.
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"
로깅 라이브러리를 만들어보자.
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');
실제 객체에 부차적인 커스텀 메타데이터 프로퍼티를 저장하여 사용할 수 있다.
이건 열거될 수 없는 보조 층이라 생각하라.(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 엘리먼트를 조작할 일이 있다고하자.
위의 사진은 잘 알려진 심볼들의 표이다. 하지만 이렇게 보면 감이 안오니 분류를 해보자.
또한 위 심볼들은 대부분 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }이다.
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"]
심볼은 내부 프라이빗 프로퍼티를 설정할 수 있다는 것은 외부로 노출되지 않은 설정을 할 수 있다는 말과 같다.
즉 여러가지 설정을 심볼로 할 수 있다.