객체의 형 변환

zimablue·2023년 10월 17일

javascript

목록 보기
27/30

자바스크립트는 형 변환이 필요할 때, 아래와 같은 알고리즘에 따라 원하는 메서드를 찾고 호출합니다.

  1. 객체에 obj[Symbol.toPrimitive](hint)메서드가 있는지 찾고, 있다면 메서드를 호출합니다. Symbol.toPrimitive는 시스템 심볼로, 심볼형 키로 사용됩니다.

  2. 1에 해당하지 않고(Symbol.toPrimitive가 없음) hint가 "string"이라면,
    obj.toString()이나 obj.valueOf()를 호출합니다.
    (존재하는 메서드만 실행됨)

  3. 1과 2에 해당하지 않고(Symbol.toPrimitive가 없음) , hint가 "number"나 "default"라면
    obj.valueOf()obj.toString()을 호출합니다.
    (존재하는 메서드만 실행됨)





ToPrimitive


특수 객체 메서드를 사용하면 숫자형이나 문자형으로의 형 변환을 원하는 대로 조절할 수 있습니다.



hint

객체 형 변환은 세 종류로 구분되는데, 'hint’라 불리는 값은 ‘목표로 하는 자료형’이며 어떤 형으로 변환할지에 대한 구분 기준이 됩니다.


'hint’는 "string", "number", "default" 세 종류가 있습니다.

1. "string"

객체를 출력하려고 할 때, 객체를 프로퍼티의 키로 사용할 때 등 문자열을 기대하는 연산을 수행할 때(객체-문자형 변환) hint는 "string"을 사용합니다.

// 객체를 출력

const obj = {}

alert(obj); // [object Object]

// 객체를 프로퍼티의 키로 사용

const obj = {}
const anotherObj = {}

anotherObj[obj] = 123

anotherObj // {[object Object]: 123}

2. "number"

수학 연산을 적용하려 할 때(객체-숫자형 변환), hint는 "number"가 됩니다.

const obj = {}

// 명시적 형 변환
let num = Number(obj); // NaN

// (이항 덧셈 연산을 제외한) 수학 연산
let n = +obj; // 단항 덧셈 연산
let delta = date1 - date2;

// 크고 작음 비교하기
let greater = user1 > user2;

3. "default"

연산자가 기대하는 자료형이 ‘확실치 않을 때’ hint는 "default"가 됩니다.

const obj1 = {}
const obj2 = {}
const user = {}

// 이항 덧셈 연산자 +는 피연산자의 자료형에 따라 문자열을 합치는 연산을 할 수도 있고 숫자를 더해주는 연산을 할 수도 있습니다. 따라서 +의 인수가 객체일 때는 hint가 default가 됩니다.
let total = obj1 + obj2;

// 동등 연산자 ==를 사용해 객체-문자형, 객체-숫자형, 객체-심볼형끼리 비교할 때도, 객체를 어떤 자료형으로 바꿔야 할지 확신이 안 서므로 hint는 default가 됩니다.
if (user == 1) { ... };





1. Symbol.toPrimitive


자바스크립트이 내장 심볼입니다.
이 심볼은 아래와 같이 목표로 하는 자료형(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





2 ~ 3. 객체에 Symbol.toPrimitive가 없을 경우


toString과 valueOf

toString과 valueOf는 심볼이 생기기 이전부터 존재해 왔던 ‘평범한’ 메서드입니다.
이 메서드를 이용하면 형 변환을 직접 구현할 수 있습니다.

자바스크립트는 객체에 Symbol.toPrimitive가 없을 경우 toString이나 valueOf를 호출합니다.


hint가 'string’인 경우

toString -> valueOf 순(toString이 있다면 toString, toString이 없다면 valueOf)으로 호출합니다.

toString은 문자열 "[object Type]"을 반환합니다.


hint가 'string’이 아닌 경우

valueOf -> toString 순으로 호출합니다.
valueOf는 객체 자신을 반환합니다.


예시 1

let user = {name: "John"};

alert(user); // [object Object]
alert(user.valueOf() === user); // true

예시 2

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.toPrimitivevalueOf가 없으면, toString이 모든 형 변환을 처리합니다.

2개의 댓글

comment-user-thumbnail
2023년 10월 17일

좋은 글 감사합니다.

1개의 답글