객체를 원시형으로 변환하기

양주영·2021년 8월 22일
0

javascript

목록 보기
2/42
  1. 객체는 논리 평가 시 true를 반환한다. 따라서 객체는 숫자형이나 문자형으로만 형 변환이 일어난다.
  2. 숫자형으로의 형 변환은 객체끼리 빼는 연산을 할 때나 수학 관련 함수를 적용할 때 일어난다.
  3. 문자형으로의 형 변환은 대개 console.log(obj)같이 객체를 출력하려고 할 때 일어난다.


📍 ToPrimitive


형 변환을 원하는대로 조절할 수 있다.
객체-원시형으로의 형 변환은 hint를 기준으로 세 종류로 구분할 수 있다.

  1. String ( 객체를 문자열로 변환하는 경우 )
// 객체를 출력하려고 함
alert(obj);

// 객체를 프로퍼티 키로 사용하고 있음
anotherObj[obj] = 123;
  1. Number ( 수학 계산 할 때 )
// 명시적 형 변환
let num = Number(obj);

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

// 크고 작음 비교하기
let greater = user1 > user2;
  1. Default ( 연산자가 기대하는 자료형이 확실하지 않을 때 )
// 이항 덧셈 연산은 hint로 `default`를 사용합니다.
let total = obj1 + obj2;

// obj == number 연산은 hint로 `default`를 사용합니다.
if (user == 1) { ... };

자바스크립트는 형 변환이 필요할 때, 아래와 같은 알고리즘에 따라 원하는 메서드를 찾고 호출한다.
1. 객체에 obj[Symbol.toPrimitive](hint)메서드가 있는지 찾고, 있다면 메서드를 호출한다.
2. Symbol.toPrimitive는 시스템 심볼로, 심볼형 키로 사용된다.
3. 1에 해당하지 않고 hint가 "string"이라면,
- obj.toString()이나 obj.valueOf()를 호출(존재하는 메서드만 실행됨).
4. 1과 2에 해당하지 않고, hint가 "number"나 "default"라면
- obj.valueOf()나 obj.toString()을 호출(존재하는 메서드만 실행됨).



📍 Symbol.toPrimitive


Symbol.toPrimitive는 시스템 심볼 중 하나이다.
아래와 같이 목표로 하는 자료형(hint)을 명명하는 데 사용된다.

obj[Symbol.toPrimitive] = function(hint) {
  // 반드시 원시값을 반환해야 합니다.
  // hint는 "string", "number", "default" 중 하나가 될 수 있습니다.
};

예시 - user객체에 객체-원시형 변환 메서드 obj[Symbol.toPrimitive](hint)를 구현해보자.

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.toPrimitive] 메서드 하나로 모든 종류의 형 변환을 다룰 수 있다.



📍 toString / valueOf


toStringvalueOf는 심볼이 존재하기 전부터 사용되던 방법이다.
Symbol.toPrimitive 가 없으면 자바스크립트가 이를 찾아 순서대로 시도한다.

  • 문자열 힌트인 경우 : toString -> valueOf
  • 그렇지 않은 경우 : valueOf -> toString

모든 형 변환을 한 곳에서 처리해야 할 경우, toString만 구현해주면 된다.

let user = {
  name: "John",

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

alert(user); // toString -> John
alert(user + 500); // toString -> John500


📍 반환타입


위에서 소개해드린 세 개의 메서드는 'hint’에 명시된 자료형으로의 형 변환을 보장해 주지 않습니다.
toString()이 항상 문자열을 반환하리라는 보장이 없고, Symbol.toPrimitive의 hint가 "number"일 때 항상 숫자형 자료가 반환되리라는 보장이 없다.
확신할 수 있는 단 한 가지는 객체가 아닌 원시값을 반환해 준다는 것뿐이다.



📝 정리


  • 원시값을 기대하는 내장 함수나 연산자를 사용할 때 객체-원시형으로의 형 변환이 자동으로 일어난다.

  • 객체-원시형으로의 형 변환은 hint를 기준으로 세 종류로 구분할 수 있다.
    1. "string" (alert 같이 문자열을 필요로 하는 연산)
    2. "number" (수학 연산)
    3. "default" (드물게 발생함)

  • 객체-원시형 변환엔 다음 알고리즘이 적용됩니다.
    1. 객체에 obj[Symbol.toPrimitive](hint)메서드가 있는지 찾고, 있다면 호출합니다.
    2. 1에 해당하지 않고 hint가 "string"이라면,

    • obj.toString()이나 obj.valueOf()를 호출합니다.
  1. 1과 2에 해당하지 않고, hint가 "number"나 "default"라면
    • obj.valueOf()나 obj.toString()을 호출합니다.
  • obj.toString() 사용해서 모든 형 변환을 한 곳에서 처리한다.



참조 : https://ko.javascript.info/object-toprimitive

profile
뚜벅뚜벅

0개의 댓글