우리는두 시간의 차이를 구하기 위하여 new Date() - new Date() 와 같이 분명 Date객체를 가지고 두 값의 차이를 구하는 -연산을 수행 하고 있고, 그리고 그것을 또 해주는 것을 볼 수 있다. 우리는 그런 특성을 보면서 형변환 중 묵시적 형변환이 되었구나, 라고 생각하곤 한다.
묵시적이라는 말의 뜻은 이와 같다. 말이나 행동으로 직접 드러내지 않고 남이 모르는 사이에 뜻을 나타내 보임.
<출처: Naver Korean-English Dictionary>
직접 드러내지 않고 남이 모르는 사이에 바뀌었다는 것인데, 그렇다면 우리 개발자들에게 드러내지 않고 있는 규칙은 무엇일까?
첫번째 규칙이다. obj[Symbol.toPrimitive](hint) 형변환이 필요한 경우 자바스크립트는 해당 객체의 Symbol.toPrimitive의 키를 갖는 함수를 연산을 할 때 필요한 자료형을 요청 하는 것으로 형변환을 수행한다.
자 그러면 형변환이 필요한 경우를 몇개 구성해보자.
첫째로 예제를 들었던 obj1 - obj2 와 같을 것이다. obj1, obj2 두 값과의 차이를 구한다는 것은 숫자일 수 밖에 없을 것이다.
두번째로 alert(obj1) 같이 obj1을 문자열로 표현을 해야 하는 경우가 있을 것이다.
세번째로 "나무" + obj1, 1 + obj2 와 같이 덧셈 연산이 있을 것이다. 이 때에는 첫번째 연산의 경우 문자열과의 덧셈이기 때문에 obj1이 식혜라는 값이면 "나무식혜"와 같이 문자열로 변환이 필요 하며, 두번째의 경우에는 숫자와의 연산이기 때문에 obj2가 2라면 3과 같이 값이 나와야 할 것 이다.
자 그러면 위의 연산들이 과연 obj[Symbol.toPrimitive] 함수를 호출 할 때 어떤 값을 hint로 제공하는지 확인 해보도록 하자.
const obj1 = {
[Symbol.toPrimitive]: function (hint) {
console.log(hint)
return hint
}
}
const obj2 = obj1
실험을 위하여 간단하게 객체 두 개를 만들었다.
첫번째 -연산에 대해서 숫자로 형변환이 필요 하기네 number를 요청하였다.
세번째는 +연산에 대해서 처리가 숫자가 필요 할 때도 있고, 문자가 필요 할때도 있기 때문에 default라는 값을 요청을 하게 되었다.
참고로 세번째의 경우 Date의 객체의 경우 아래 처럼 표현 된다. + 연산에 대해서 문자열 표현을 더 우선적으로 하고 있다.
우리는 아래와 같이 형변환을 유도 할 수 있을 것이다.
const book = {
price: 100,
title: 'book',
[Symbol.toPrimitive]: function (hint) {
if( hint === 'number' ) {
return this.id
}
return this.value
}
}
const book2 = { ...book, price: 200, title: 'book 2' }
book2 - book
// 100
book2 + book
// book 2book
alert(book)
// book
Symbol이 나오기 전에도 우리는 객체간의 연산을 수행 했다. es6이전에 말이다. 그렇다는 것은 [Symbol.toPrimitive]를 사용 할 수 없었어도 사용 했다는 말이다. 아래처럼 말이다. 뭐 물론 아래의 경우에는 아래에 [Symbol.toPrimitive]를 정의 하지 않은 객체에 대한 표현이 있다.
뭐 hint가 number인 - 연산의 경우 정의 한것이 없으니 NaN인 것은 이해 하겠다만 default인 경우 "[object Object][object Object]"왜 이렇게 나타날까?
이럴때 사용하는 것이 toString, valueOf 함수이다.
const book = {
price: 100,
title: 'book',
toString: function() {
return this.title
},
valueOf: function() {
return this.price
}
}
const book2 = { ...book, price: 200, title: 'book 2' }
book2 - book
// 100
book2 + book
// 300
alert(book)
// book
위에서 유심히 살펴 볼만한 내용은 book2 + book의 값이 300인 것을 볼 수 있다. 즉 default의 경우 valueOf가 적용 되었다는 것을 볼 수 있다. 규칙은 아래와 같다.
string 힌트의 경우 toString을 우선 적용 없는 경우 valueOf를 적용
number, default 힌트의 경우 valueOf를 우선 적용 없는 경우 toString을 호출 하게 된다.
어떠한 함수도 없는 경우
Uncaught TypeError: Cannot convert object to primitive value 에러를 발생하게 된다.
댓글
댓글 쓰기