자바스크립트는 형 변환이 필요할 때, 아래와 같은 알고리즘에 따라 원하는 메서드를 찾고 호출합니다.
객체에 obj[Symbol.toPrimitive](hint)메서드가 있는지 찾고, 있다면 메서드를 호출합니다. Symbol.toPrimitive는 시스템 심볼로, 심볼형 키로 사용됩니다.
1에 해당하지 않고(Symbol.toPrimitive가 없음) hint가 "string"이라면,
obj.toString()이나 obj.valueOf()를 호출합니다.
(존재하는 메서드만 실행됨)
1과 2에 해당하지 않고(Symbol.toPrimitive가 없음) , hint가 "number"나 "default"라면
obj.valueOf()나 obj.toString()을 호출합니다.
(존재하는 메서드만 실행됨)
특수 객체 메서드를 사용하면 숫자형이나 문자형으로의 형 변환을 원하는 대로 조절할 수 있습니다.
객체 형 변환은 세 종류로 구분되는데, 'hint’라 불리는 값은 ‘목표로 하는 자료형’이며 어떤 형으로 변환할지에 대한 구분 기준이 됩니다.
'hint’는 "string", "number", "default" 세 종류가 있습니다.
객체를 출력하려고 할 때, 객체를 프로퍼티의 키로 사용할 때 등 문자열을 기대하는 연산을 수행할 때(객체-문자형 변환) hint는 "string"을 사용합니다.
// 객체를 출력
const obj = {}
alert(obj); // [object Object]
// 객체를 프로퍼티의 키로 사용
const obj = {}
const anotherObj = {}
anotherObj[obj] = 123
anotherObj // {[object Object]: 123}
수학 연산을 적용하려 할 때(객체-숫자형 변환), hint는 "number"가 됩니다.
const obj = {}
// 명시적 형 변환
let num = Number(obj); // NaN
// (이항 덧셈 연산을 제외한) 수학 연산
let n = +obj; // 단항 덧셈 연산
let delta = date1 - date2;
// 크고 작음 비교하기
let greater = user1 > user2;
연산자가 기대하는 자료형이 ‘확실치 않을 때’ hint는 "default"가 됩니다.
const obj1 = {}
const obj2 = {}
const user = {}
// 이항 덧셈 연산자 +는 피연산자의 자료형에 따라 문자열을 합치는 연산을 할 수도 있고 숫자를 더해주는 연산을 할 수도 있습니다. 따라서 +의 인수가 객체일 때는 hint가 default가 됩니다.
let total = obj1 + obj2;
// 동등 연산자 ==를 사용해 객체-문자형, 객체-숫자형, 객체-심볼형끼리 비교할 때도, 객체를 어떤 자료형으로 바꿔야 할지 확신이 안 서므로 hint는 default가 됩니다.
if (user == 1) { ... };
자바스크립트이 내장 심볼입니다.
이 심볼은 아래와 같이 목표로 하는 자료형(hint)을 명명하는 데 사용됩니다.
obj[Symbol.toPrimitive] = function(hint) {
// 반드시 원시값을 반환해야 합니다.
// hint는 "string", "number", "default" 중 하나가 될 수 있습니다.
};
let user = {
name: "Zima",
age: 100,
[Symbol.toPrimitive](hint) {
alert(`hint: ${hint}`);
// hint: string
// hint: number
// hint: default 순으로 알림
if (hint === 'number') {
return this.age;
} else if(hint === 'string') {
return this.name
} else if(hint === "default") {
return this.age
}
}
};
// 문자형 변환이기 때문에 "string"이 hint로 주어짐
alert(user); // "Zima"
// 숫자형 변환이기 때문에 "number"이 hint로 주어짐
alert(+user); // 100
// 연산자가 기대하는 자료형이 확실치 않기 때문에 "default"가 hint로 주어짐
alert(user + 500); // 600
toString과 valueOf는 심볼이 생기기 이전부터 존재해 왔던 ‘평범한’ 메서드입니다.
이 메서드를 이용하면 형 변환을 직접 구현할 수 있습니다.
자바스크립트는 객체에 Symbol.toPrimitive가 없을 경우 toString이나 valueOf를 호출합니다.
toString -> valueOf 순(toString이 있다면 toString, toString이 없다면 valueOf)으로 호출합니다.
toString은 문자열 "[object Type]"을 반환합니다.
valueOf -> toString 순으로 호출합니다.
valueOf는 객체 자신을 반환합니다.
let user = {name: "John"};
alert(user); // [object Object]
alert(user.valueOf() === user); // true
let user = {
name: "Zima",
age: 100,
// hint가 "string"인 경우
toString() {
return this.name
},
// hint가 "number"나 "default"인 경우
valueOf() {
return this.age;
}
};
alert(user); // toString -> {name: "Zima"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 600
만약 객체에 Symbol.toPrimitive와 valueOf가 없으면, toString이 모든 형 변환을 처리합니다.
좋은 글 감사합니다.