심벌이란?
- ES6 에서 도입된 변경 불가능한 원시 타입의 값이다.
- 심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다.
- 주로 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용한다.
심벌 값의 생성
Symbol 함수
- 리터럴 표기법을 통해 생성할수 없고, Symbol 함수를 호출하여 생성해야 한다.
- 이때 생성된 심벌 값은 외부로 노출되지 않아 확인할 수 없으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.
- 심벌 값도 문자열, 숫자, 불리언과 같이 객체 처럼 접근하면 암묵적으로 래퍼 객체를 생성한다.
const test = Symbol()
const test1 = Symbol('test')
const test2 = Symbol('test')
test === test2
심벌과 상수
- 아래 예제 처럼 상수 값에 의미가 있는게 아니라 상수 이름 자체에 의미가 있는 경우가 있다.
- 이때 상수 값이 변경 될 수도 있고, 다른 변수값과 중복될수도 있다.
- 이러한 경우 변경,중복될 가능성이 있는 무의미한 상수 대신 중복될 가능성이 없는 심벌값을 사용할 수 있다.
const d = {
UP : Symbol('up'),
DOWN : Symbol('down'),
LEFT : Symbol('left'),
RIGHT : Symbol('right'),
}
const myd = d.UP
심벌과 프로퍼티 키
심벌을 프로퍼티 키로 사용하기
- 빈 문자열을 포함하는 모든 문자열 또는 심벌 값으로 만들 수 있으며, 동적으로 생성 할 수도 있다.
- 심벌 값을 프로퍼티 키로 사용하려면 프로퍼티 키로 사용할 심벌 값에 대괄호를 사용해야 하고, 프로퍼티에 접근할 때도 마찬가지로 대괄호를 사용해야 한다.
- 심벌값을 프로퍼티 키로 만들면 다른 프로퍼티 키와 절대 충돌하지 않는다.
const obj = {
[Symbol.for('test1')] :1
}
obj[Symbol.for('test1')]
심벌과 프로퍼티 은닉
- 심벌 값을 프로퍼티 키로 사용하여 생성한 프로퍼티는
for … in 문이나 Object.keys, Object.getOwnPropertyNames 메서드로 찾을 수 없다.
- 즉, 외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있다.
- 하지만, ES6에서 도입된
Object.getOwnPropertySymbols 메서드로 찾을 수 있다.
심벌과 표준 빌트인 객체 확장
- 일반적으로 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가하여 확장하는 것은 권장하지 않고, 읽기 전용으로 사용하는 것이 좋다.
Symbol 메소드
자주 사용하는 Symbol 메소드
const a = Symbol("desc");
const b = Symbol("desc");
console.log(a === b);
const c = Symbol.for("shared");
const d = Symbol.for("shared");
console.log(c === d);
console.log(Symbol.keyFor(c));
console.log(Symbol.keyFor(a));
const obj = {};
const sym = Symbol("secret");
obj[sym] = "hidden value";
obj.name = "Min";
console.log(Object.getOwnPropertySymbols(obj));
console.log(Object.keys(obj));
console.log(Reflect.ownKeys(obj));
const arr = [1, 2, 3];
const it = arr[Symbol.iterator]();
console.log(it.next());
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield "A"; yield "B";
}
};
(async () => {
for await (const v of asyncIterable) console.log(v);
})();
console.log(a.toString())
class Dog {
get [Symbol.toStringTag]() {
return "Puppy";
}
}
console.log(Object.prototype.toString.call(new Dog()));
class MyClass {
static [Symbol.hasInstance](obj) {
return obj.type === "custom";
}
}
console.log({ type: "custom" } instanceof MyClass);
const money = {
value: 1000,
[Symbol.toPrimitive](hint) {
if (hint === "number") return this.value;
if (hint === "string") return `$${this.value}`;
return this.value;
}
};
console.log(+money);
console.log(`${money}`);
const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2));