Symbol.toPrimitive
란?
- 잘 알려진 심볼 중 하나이다.
- 강제 타입변환 시에 타입변환 힌트를 받아들이고, 어떤 원시 타입을 반환할지에 대한 메서드를 정의할 수 있다.
- 객체를 primitive value 로 변경하는 강력한 방법을 제공한다.
- JS 에서는 다양한 경우에 값을 강제로 변환한다.
- ex)
+object
인 경우 숫자로 강제 변환한다.String(object)
인 경우엔 문자열로 변환한다. - 내부적으로
hint
라는 인자를 받게 된다. number
,string
,default
중 하나를 받아 선호하는 타입이 무엇인지 체크할 수 있다.
- 모든 타입 변환 알고리즘에서 우선순위를 갖는다.
toString()
이나valueOf()
보다 앞선 우선순위를 갖는다.toString()
은 해당 타입을 문자열로 변환할 때 사용한다.valueOf()
는 해당 타입을 오브젝트로 변환할 때 사용한다.
객체의 [Symbol.toPrimitive]
오버라이드 해보기
const normalObject = {};
console.log(+normalObject); // NaN
console.log(`${normalObject}`); // [object Object]
console.log("" + normalObject); // [object Object]
const object1 = {
// hint 를 이용한 로직을 작성할 수 있다.
[Symbol.toPrimitive](hint) {
console.log(`hint was ${hint}`);
if (hint === "number") {
return 42;
}
if (hint === "string") {
return "forty two";
}
return "default";
},
};
// hint: number
console.log(+object1); // 42
// hint: string
// 템플릿 리터럴 내의 오브젝트는 String(object1); 을 한 것과 동일하다.
// 타입을 primitive string 으로 바꿔준다.
console.log(`${object1}`); // "forty two"
// hint: default
// 더하기 연산자는 문자열과 숫자 모두 가능하다.
console.log("" + object1); // "default"
타입 강제변환 시 들어온 힌트에 따라 적절한 형태의 primitive type 으로 변환할 수 있다. 용도 자체가 primitive type 으로 변환시키기 위한 접근자 프로퍼티여서, primitive type 이 아닌 다른 타입으로 반환하면, 아래와 같은 에러를 만날 수 있다.
Uncaught TypeError: Cannot convert object to primitive value
직접 호출한다면?
const object1 = {
[Symbol.toPrimitive](hint) {
console.log(`hint was ${hint}`);
if (hint === "number") {
return 42;
}
if (hint === "string") {
return "forty two";
}
return "default";
},
};
console.log(object1[Symbol.toPrimitive]());
// hint was undefined
// default
보통 직접 호출할 일은 없지만, 직접 호출하면 힌트로는 undefined
가 적용된다.
기본 정의 살펴보기
[Symbol.toPrimitive](hint) {
let methods = hint === "string"
? ["toString", "valueOf"]
: ["valueOf", "toString"];
for (const methodName of methods) {
const method = this[methodName];
if(typeof method === "function") {
const result = method.call(this);
if(result === null || typeof result !== "object") {
return result;
}
}
}
throw new TypeError();
};
힌트가 string
으로 들어오면, toString()
이 함수로 정의되어 있는지 먼저 확인하고 호출해본다. 이후 결과 값이 적절한지 판단 후 반환한다. stirng
이 아니라면, valueOf()
를 우선순위로 두고 같은 동작을 한다.
만일 적절한 메서드가 없다면 TypeError
를 던진다.
Date
의 toPrimitive
동작 살펴보기
const date = new Date();
console.log(String(date)); // hint: string, Tue Jan 31 2023 00:03:19 GMT+0900 (한국 표준시)
console.log(+date); // hint: number, 1675090999694
console.log("" + date); // hint: default, Tue Jan 31 2023 00:03:19 GMT+0900 (한국 표준시)
console.log(date[Symbol.toPrimitive]()); // hint: undefined, Uncaught TypeError: Invalid hint: undefined
default
일 때와string
일 때가 같다.undefined
인 경우 에러가 난다.
'자바스크립트 > 개념' 카테고리의 다른 글
자바스크립트 오브젝트 프로퍼티의 순서 (0) | 2023.01.01 |
---|---|
Object.prototype.valueOf() 란? (0) | 2023.01.01 |
데이터 프로퍼티 (data property)와 접근자 프로퍼티 (accessor property) 란? (0) | 2023.01.01 |
자바스크립트의 Descriptor 란? (feat. Object.defineProperty()) (0) | 2023.01.01 |
Symbol.species 심볼과 용례 (0) | 2022.12.24 |