on your mark
[JAVASCRIPT.INFO] 4.8 객체를 원시형으로 변환하기 본문
4.8 객체를 원시형으로 변환하기
obj1 + obj2
, obj1 - obj2
, alert(obj)
등과 같은 경우에 자동 형 변환이 일어나고 객체는 원시값으로 변환된다.
ToPrimitive
객체 형 변환은 세 종류로 구분되는데 'hint'(목표로 하는 자료형)라 불리는 값이 구분 기준이 된다.
"string"
alert
함수 같이 문자열을 기대하는 연산을 수행할 때는(객체-문자형 변환) hint가 string
이 된다.
alert(obj); // 객체를 출력
anotherObj[obj] = 123; //객체를 프로퍼티 키로 사용
"number"
수학 연산을 적용하려 할 때(객체-숫자형 변환), hint는 number
가 된다.
let num = Number(obj); // 명시적 형 변환
// (이항 덧셈을 제외한) 수학 연산
let n = +obj; // 단항 덧셈 연산
let delta = date1 - date2;
// 크고 작음 비교하기
let greater = user1 > user2;
"default"
연산자가 기대하는 자료형이 '확실치 않을 때' hint는 default
가 된다.
이항 덧셈 연산자 +
는 피연산자의 자료형에 따라 문자열을 합치는 연산을 할 수도 있고 숫자를 더해주는 연산을 할 수 있다. 따라서 +
의 인수가 객체일 때는 hind가 default
가 된다.
동등 연산자 ==
를 사용해 객체-문자형, 객체-숫자형, 객체-심볼형끼리 비교할 때도, 객체를 어떤 자료형으로 바꿔야 할지 모르므로 hint는 deafult가 된다.
// 이항 덧셈 연산은 hint로 'default'를 사용한다.
let total = obj1 + obj2;
// obj == number 연산은 hint로 'default'를 사용한다.
if(user == 1) {...};
크고 작음을 비교할 때 쓰이는 연산자 <, >
역시 피연산제에 문자형과 숫자형 둘 다 허용하는데, 이 연산자들은 hint를 'number'로 고정한다.
Date
객체를 제외한 모든 내장 객체는 hint가 deafult
인 경우와 number
인 경우를 동일하게 처리한다.
자바스크립트는 형 변환이 필요할 때, 아래와 같은 알고리즘에 따라 원하는 메서드를 찾고 호출한다.
- 객체에
obj[Symbol.toPrimitive](hint)
메서드가 있는지 찾고, 있다면 메서드를 호출한다.Symbol.toPrimitive
는 시스템 심볼로, 심볼형 키로 사용된다. - 1에 해당하지 않고 hint가
"string"
이라면,obj.toString()
이나obj.valueOf()
를 호출
- 1과 2에 해당하지 않고, hint가
"number"
나"default"
라면obj.valueOf()
나obj.toString()
을 호출
Symbol.toPrimite
자바스크립트엔 Symbol.toPrimitive
라는 내장 심볼이 존재한다. 이 심볼은 목표로 하는 자료형(hint)를 명명하는 데 사용된다.
obj[Symbol.toPrimitive] = function(hint) {
// 반드시 원시값을 반환해야 함
// hint는 'string', 'number', 'default' 중 하나
}
let user = {
name: "John",
money: 1000,
[Symbol.toPrimitive](hint) {
alert(`hint: ${hint}`);
return hint == "string" ? `{name: "${this.name}"` : this.money;
}
}
alert(user); // hint: string -> {name:"John"}
alert(+user); // hint: number -> 1000
alert(user+500); // hint: default -> 1500
user
는 hint에 따라 문자열로 변환되기도 하고 숫자로 변환되기도 한다. user[Symbol.toPrimitve]
를 사용하면 메서드 하나로 모든 종류의 형 변환을 다룰 수 있다.
toString과 valueOf
이 메서드를 이용하면 형 변환을 직접 구현할 수 있다.
객체에 Symbol.toPrimitive
가 없으면 자바스크립트는 아래 규칙에 따라 toString
이나 valueOf
를 호출한다.
- hint가 'string'인 경우:
toString -> valueOf
순 (toString
이 있다면toString
을 호출,toString
이 없다면valueOf
를 호출) - 그 외:
valueOf -> toString
순
이 메서드들은 반드시 원시값을 반환해야 한다. toString
이나 valueOf
가 객체를 반환하면 그 결과는 무시된다.
toString
은 문자열"[object Object]"
를 반환valueOf
는 객체 자신을 반환
let user = {name: "John"};
alert(user); // [object Object]
alert(user.valueOf() === user); // true
이런 이유로 alert
에 객체를 넘기면 [object Object]
가 출력된다.
let user = {
name: "John",
money: 1000,
//hint가 "string"인 경우
toString() {
return `name: "${this.name}"}`;
}
//hint가 "number"나 "default"인 경우
valueOf() {
return this.money;
}
}
alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500
Symbol.toPrimitive
를 사용한 예제와 동일하게 나온다.
let user = {
name: "John",
toString() {
return this.name;
}
};
alert(user); // toString -> John
alert(user + 500); // toString -> John500
객체에 Symbol.toPrimitive
와 valueOf
가 없으면, toString
이 모든 형 변환을 처리
반환 타입
위의 세 개의 메서드는 'hint'에 명시된 자료형으로의 형 변환을 보장해 주지 않는다.
toString()
이 항상 문자열을 반환하리라는 보장이 없고, Symbol.toPrimitive
의 hint가 "number"
일 때 항상 숫자형 자료가 반환되리라는 보장이 없다. 확신할 수 있는 단 한가지는 원시값을 반환해 준다는 것이다.
toString
이나 valueOf
가 객체를 반환해도 에러가 발생하지 않는다. 다만 이때는 반환 값이 무시된다. 반면에 Symbol.toPrimitive
는 무조건 원시자료를 반환해야 한다. 그렇지 않으면 에러가 발생한다.
추가 형 변환
상당수의 연산자와 함수가 피연산자의 형을 변환시킨다. 객체가 피연산자일 때는 다음과 같은 단계를 거쳐 형 변환이 일어난다.
- 객체는 원시형으로 변화된다. (변환 규칙은 위 참고)
- 변환 후 원시값이 원하는 형이 아닌 경우엔 또다시 형 변환이 일어난다.
let obj = {
// 다른 메서드가 없으면 toString에서 모든 형변환을 처리
toString() {
return "2";
}
}
alert(obj * 2); // 4 객체가 문자열 "2"로 바뀌고, 곱셈 연산 과정에서 문자열 "2"는 숫자 2로 변경됨
obj*2
에서 객체가 원시형으로 변화되므로toString
에 의해obj
는 문자열"2"
가 된다.- 곱셈 연산은 문자열은 숫자형으로 변환시키므로
2*2
가 된다.
let obj = {
toString() {
return "2";
}
}
alert(obj + 2); //22 문자열이 반환되기 때문에 문자열끼리의 병합이 일어남
'WEB > Javascript' 카테고리의 다른 글
[JAVASCRIPT.INFO] 5.2 숫자형 (1) | 2023.01.02 |
---|---|
[JAVASCRIPT.INFO] 5.1 원시값의 메서드 (0) | 2022.12.31 |
[JAVASCRIPT.INFO] 4.7 심볼형 (0) | 2022.12.28 |
[JAVASCRIPT.INFO] 4.6 옵셔널 체이닝 '?.' (0) | 2022.12.28 |
[JAVASCRIPT.INFO] 4.5 new 연산자와 생성자 함수 (0) | 2022.12.28 |