# 객체 원시형 변환 ToPrimitive

hint

  • 객체의 형 변환의 기준이 되는 것
  • string, default, number

# hint : string

문자열을 기대하는 연산 수행

  1. alert 함수
  2. 객체의 프로퍼티 키
// 객체를 출력하려고 함
alert(obj);

// 객체를 프로퍼티 키로 사용하고 있음
anotherObj[obj] = 123;
1
2
3
4
5

# hint : number

수학 연산 적용

  1. 명시적 형 변환
let num = Number(obj);
1
  1. (이항 덧셈 연산을 제외한) 수학 연산
let n = +obj; // 단항 덧셈 연산
let delta = date1 - date2;
1
2
  1. 크고 작음 비교하기
let greater = user1 > user2;
1

# hint : default

연산자가 기대하는 자료형이 확실치 않을 때

  • 덧셈 연산자 + 는 피연산자의 자료형에
    1. 문자열을 합치는 연산
    2. 숫자를 더해주는 연산

+ 의 인수가 객체일 때는 default 가 된다.

  • 동등 연산자 ==
    • 객체-문자형, 객체-숫자형, 객체-심볼형 끼리 비교
    • 객체를 어떤 자료형으로 바꿔야 할지 확신이 없으므로 default 가 된다.

# boolean

모든 객체는 true 이다.

# 자바스크립트 형 변환의 알고리즘

  1. 객체에 obj[Symbol.toPrimitive](hint) 메서드 존재 확인
    • 2-1 존재하면 호출한다.
    • 2-2 없을 때
      • 3-1 hint 가 'string'
        • obj.toString() || obj.valueOf() 의 존재를 확인하고 호출
      • 3-2 hint 가 'number' / 'default'
        • obj.valueOf() || obj.toString() 의 존재를 확인하고 호출

# Symbol.toPrimitive

  • 자바스크립트의 내장 심볼
  • 목표로 하는 자료형(hint) 를 명명한다.
obj[Symbol.toPrimitive] = function(hint) {
  // 반드시 원시값을 반환해야 합니다.
  // hint는 "string", "number", "default" 중 하나가 될 수 있습니다.
};
1
2
3
4
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# toString 과 valueOf

toStringvalueOf

  • 심볼이 생기기 이전부터 존재하던 메서드
  • 형 변환을 직접 구현할 수 있다.
  • 반드시 원시값을 반환해야 한다.
  • 객체를 반환하면 그 결과는 무시된다.
  • toString 의 기본 규칙: 문자열 "[object Object]" 반환
  • valueOf 는 객체 자신을 반환
let user = {name: "John"};

alert(user); // [object Object]
alert(user.valueOf() === user); // true
1
2
3
4
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

모든 형 변환을 한 곳에서 처리하고 싶을 땐 toString 만 구현해 준다.

let user = {
  name: "John",

  toString() {
    return this.name;
  }
};

alert(user); // toString -> John
alert(user + 500); // toString -> John500
1
2
3
4
5
6
7
8
9
10

# 반환 타입

toString() Symbol.toPrimitive valueoOf()

  • 항상 hint 자료형의 반환을 보장해 주지 않음.
  • 원시값의 반환만 보장해줌

과거의 잔재

  • toString / valueOf가 객체를 반환
    • 반환 값이 무시, 메서드 자체가 존재하지 않았던 것처럼 동작
    • 과거 자바스크립트엔 '에러’ 개념이 잘 정립되어있지 않았기 때문
  • Symbol.toPrimitive
    • 무조건 원시자료를 반환
    • 원시자료를 반환하지 않으면 에러 발생

# 추가 형 변환

  1. 객체가 피연산자일 때 객체는 원시형으로 변화함.
  2. 변환 후 원시값이 원하는 형이 아닌 경우 또 다시 형 변환이 일어남
let obj = {
  // 다른 메서드가 없으면 toString에서 모든 형 변환을 처리합니다.
  toString() {
    return "2";
  }
};

alert(obj * 2); // 4, 객체가 문자열 "2"로 바뀌고, 곱셈 연산 과정에서 문자열 "2"는 숫자 2로 변경됩니다.
alert(obj + 2); // 22("2" + 2), 문자열이 반환되기 때문에 문자열끼리의 병합이 일어났습니다.
1
2
3
4
5
6
7
8
9