Posts 모던 자바스크립트 #4.8. 객체를 원시형으로 변환하기
Post
Cancel

모던 자바스크립트 #4.8. 객체를 원시형으로 변환하기

모던 JavaScript 튜토리얼을 따라가면서 정리합니다.

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

객체는 논리 평가 시 true를 반환한다. 객체는 숫자형이나 문자형으로만 형변환이 일어난다고 생각하면 된다.

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

특수 객체 메서드를 사용하면 숫자형이나 문자형으로의 형변환을 원하는 대로 조절할 수 있다. 객체-원시형으로의 형 변환은 hint라고 불리는 값을 기준으로 세 종류로 구분할 수 있다. hint는 목표로 하는 자료형이다.

  • "string": alert 같이 문자열을 필요로 하는 연산, 객체를 프로퍼티 키로 사용할 때(anotherObj[obj]-123)

  • "number": 명시적 형변환(Number(obj)), 수학 연산, 크고 작음 비교하기

    ex) 크고 작음을 비교할 때 쓰이는 연산자 <, >는 피연산자에 문자형과 숫자형을 다 허용하는데, 이 연산자들은 hint를 default가 아닌 number로 고정한다. (하위 호환성 때문에 정해진 규칙)

  • "default": 연산자가 기대하는 자료형이 ‘확실치 않을 때’. 드물게 발생

    ex) 이항덧셈연산자 +: 피연산자의 자료형에 따라 문자열을 합치는 연산을 할 수도 있고, 숫자를 더해주는 연산을 할 수도 있다.

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

내장 객체는 대개 hint가 "default"일 때와 "number"일 때를 동일하게 처리한다. 따라서 실무에서는 hint가 "default"인 경우와 "number"인 경우를 합쳐서 처리하는 경우가 많다.

"boolean" hint는 존재하지 않는다. 모든 객체는 그냥 true로 평가된다. 우리도 내장 객체에 사용되는 규칙처럼 "default""number"를 동일하게 처리하면, 결국엔 두 종류의 형변환(객체-문자형, 객체-숫자형)만 남게 된다.

객체-원시형 변환엔 다음의 알고리즘이 적용된다.

  • 객체엔 obj[Symbol.toPrimitive](hint) 메서드가 있는지 찾고, 있다면 호출한다.

  • 1에 해당하지 않고 hint가 "string"이라면

    obj.toString()이나 obj.valueOf를 호출한다. (존재하는 메서드만 실행됨)

  • 1과 2에 해당하지 않고 hint가 "number""default"라면

    obj.valueOf()obj.toString()을 호출한다. (존재하는 메서드만 실행됨)

Symbol.toPrimitive

자바스크립트에는 Symbol.toPrimitive라는 내장 심볼이 존재하는데, 이 심볼은 목표로 하는 자료형(hint)을 명명하는 데 사용된다.

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

예시: user 객체에 객체-원시형 반환 메서드 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

toString과 valueOf

이 메서들은 반드시 원시값을 반환해야 한다. 객체를 반환하면 그 결과는 무시된다. 일반 객체는 기본적으로 toStringvalueOf에 적용되는 다음 규칙을 따른다.

  • toString은 문자열 "[object Object]"를 반환한다.
  • valueOf는 객체 자신을 반환한다.

예시: usertoStringvalueOf를 조합해 만들었다. Symbol.toPrimitive를 사용한 예시와 동일하게 동작한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
let user = {
  name: "John",
  money: 1000,
  
  // hint가 "string"인 경우
  toString() {
    return `{name: "${this.name}"}`;
  },
  // hint가 "number"나 "default"인 경우
  valueOf() {
    return this.money;
  }
}

간혹 모든 형변환을 한 곳에서 처리해야 하는 경우도 생긴다. 이럴 땐 toString만 구현해준다.

1
2
3
4
5
6
7
8
9
10
let user = {
  name: "John",
  
  toString() {
    return this.name;
  }
};

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

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

반환 타입

위 세 개의 메서드는 ‘hint’에 명시된 자료형으로의 형변환을 보장해주지 않는다. 확신할 수 있는 단 한 가지는 객체가 아닌 원시값을 반환해준다는 것 뿐이다.

추가 형변환

객체가 피연산자일 때는 다음과 같은 단계를 거쳐 형변환이 일어난다.

  • 객체를 원시형으로 변환한다.
  • 변환 후 원시값이 원하는 형이 아닌 경우 또 다시 형변환이 일어난다.
1
2
3
4
5
6
7
let obj = {
  toString() {
    return "2";
  }
};

alert(obj * 2); // 4, 객체가 문자열 "2"로 바뀌고, 곱셈 연산 과정에서 문자열 "2"는 숫자 2로 변경된다.
This post is licensed under CC BY 4.0 by the author.

이것이 안드로이드다 with 코틀린 #1 코틀린 기본문법: 1. 코딩 준비하기

이것이 안드로이드다 with 코틀린 #1 코틀린 기본문법: 2. 변수와 상수

Loading comments from Disqus ...