티스토리 뷰

4.8 Object to primitive conversion

Conversion rules

  • 불리언으로 변환되지는 않는다.
  • 숫자 변환은 객체를 빼거나 수학적인 함수가 적용될 때 발생된다.
  • 문자열로의 변환 일반적으로 어떤 결과를 반환하는 동작에서 발생한다. (alert 같은 것)

hints

객체가 원시타입으로 변환될 때에 '힌트'라는 메커니즘이 존재하는데, 말 그대로 이 힌트가 변환하려는 객체가 어떤 타입으로 변환할지 힌트를 준다.

 

"string" - 문자열로 변환되는 경우 (alert와 같이 반환값에 문자열이 기대되는 동작)

// output
alert(obj);

// using object as a property key
anotherObj[obj] = 123;

 

"number" - 숫자로 변환되는 경우 (수학적인 연산 동작 등)

// explicit conversion
let num = Number(obj);

// maths (except binary plus)
let n = +obj; // unary plus
let delta = date1 - date2;

// less/greater comparison
let greater = user1 > user2;

문제는 "default"인데, 무엇으로 변환될지 확실하게 알 수 없을 때 발생한다. binary 연산의 경우 문자열과 숫자 모두에서 작동할 수 있으므로, default 힌트를 사용한다. (추가적인것은 아래 참조)

// binary plus uses the "default" hint
let total = obj1 + obj2;

// obj == number uses the "default" hint
if (user == 1) { ... };

비교 연산, 내장 객체(Date 제외)는 "default" 힌트를 사용한다. 

 

 

javascript에서 객체 형변환을 과정에서 일어나는 일들..

  1. Symbol.toPrimitive 메서드를 호출한다. (symbol 키를 원시타입으로 변환하는 메서드)만약 해당 메서드가 존재하지 않는다면 힌트를 사용
  2. 힌트가 "string" 일 때, toString() 또는 obj.valueOf() 호출
  3. 힌트가 "number"거나 "default"일 때, obj.valueOf()나 obj.toString() 호출symbol.toPrimitive

Symbol.toPrimitive

obj[Symbol.toPrimitive] = function(hint) {
  // here goes the code to convert this object to a primitive
  // it must return a primitive value
  // hint = one of "string", "number", "default"
};
let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// conversions demo:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500

toString/valueOf

toString : "string" 힌트를 위한 함수이다. 스트링으로 변환하고 싶거나, 기본타입 대신에 객체를 반환하고 싶을 때

valueOf : "string" 외에 다른 힌트를 위한 함수이다. 

 

toString은 "[object Object]"를 반환하고, valueOf 함수는 객체 그 자체를 반환한다.

let user = {name: "John"};

alert(user); // [object Object]
alert(user.valueOf() === user); // true
let user = {
  name: "John",
  money: 1000,

  // for hint="string"
  toString() {
    return `{name: "${this.name}"}`;
  },

  // for hint="number" or "default"
  valueOf() {
    return this.money;
  }

};

alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday