Growth from the root - Vanilla JavaScript - 객체를 원시형으로

이형준·2023년 4월 10일
0
post-thumbnail

객체 -> 원시형

📃 객체끼리 더하고, 빼는 연산을 하면 어떻게 될까 모든 경우에서 객체는 원시값으로 변환되고, 의도한 연산이 수행됨.

  1. 객체는 예외없이 논리평가시 true를 반환, 따라서 객체는 숫자형이나 문자형으로만 형 변환 됨.
  2. 숫자형으로 변환된 객체는 수학 연산을 할 떄나 수학 관련 함수를 적용할 때 적용.
  3. 문자형으로 형 변환은 대개 alert(obj) 같이 객체를 출력하라고 할 때 일어남.



ToPrimitive

📃 ToPrimitive을 사용하면 숫자형이나 문자형으로의 변환을 원하는 대로 조절 가능함, 객체의 형 변환은 세 종류로 구분되는데 hint라 불리는 값이 구분 기준이 됨, 목표로 하는 자료형 정도로 이해하면 편함.

"String"

📃 alert 함수 같이 문자열을 기대하는 연산을 수행할 때는(객체-문자형 변환), hint가 string이 됨.

// 객체를 출력하려고 함
alert(obj);

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

"Number"

📃 수학 연산을 적용하려 할 때(객체-숫자형 변환), hint가 number이 됨.

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

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

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

"Default"

📃 연산자가 기대하는 자료형이 확실하지 않을 때, 아주 드물게 발생함.

// 이항 덧셈 연산은 hint로 `default`를 사용합니다.
let total = obj1 + obj2;

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



Symbol.toPromitive

📃 이 심볼은 아래와 같이 목표로 하는 자료형(hint)을 명명하는데 사용함.

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

ex)

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 는 힌트에 따라 문자열로 변환되기도, 숫자로 변환되기도 함.



toString과 valueOf

📃 이런 메서드를 사용하면 형 변환을 직접 구현 할 수 있음.

  1. 객체는 예외없이 논리평가시 true를 반환, 따라서 객체는 숫자형이나 문자형으로만 형 변환 됨.
  2. 숫자형으로 변환된 객체는 수학 연산을 할 떄나 수학 관련 함수를 적용할 때 적용.
  3. 문자형으로 형 변환은 대개 alert(obj) 같이 객체를 출력하라고 할 때 일어남.

ex)

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

✏️ 출력 결과가 Symbol.toPrimitive를 사용한 예제와 완전히 동일하다는 걸 확인할 수 있음.



✅ obj.toString()만 사용해도 '모든 변환’을 다 다룰 수 있기 때문에, 실무에선 obj.toString()만 구현해도 충분한 경우가 많습니다. 반환 값도 ‘사람이 읽고 이해할 수 있는’ 형식이기 때문에 실용성 측면에서 다른 메서드에 뒤처지지 않습니다. obj.toString()은 로깅이나 디버깅 목적으로도 자주 사용됩니다.

profile
프론트엔드 개발자 이형준입니다.

0개의 댓글