Skip to content

Commit 18efe9a

Browse files
[객체를 원시형으로 변환하기] 보완
1 parent a8cceae commit 18efe9a

File tree

1 file changed

+28
-28
lines changed
  • 1-js/04-object-basics/05-object-toprimitive

1 file changed

+28
-28
lines changed

1-js/04-object-basics/05-object-toprimitive/article.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55

66
이 모든 경우에 자동 형 변환이 일어납니다. 객체는 원시값으로 변환되고, 그 후 의도한 연산이 수행됩니다.
77

8-
<info:type-conversions> 챕터에선 객체의 형 변환은 다루지 않았습니다. 원시형 자료가 어떻게 문자, 숫자, 논리형으로 변환되는지만 알아보았죠. 이젠 메서드와 심볼에 대한 지식을 갖추었으니 본격적으로 이 공백을 메꿔보도록 합시다.
8+
<info:type-conversions> 챕터에선 객체의 형 변환은 다루지 않았습니다. 원시형 자료가 어떻게 문자, 숫자, 논리형으로 변환되는지만 알아보았죠. 이젠 메서드와 심볼에 대한 지식을 갖추었으니 본격적으로 이 공백을 메꿔봅시다.
99

10-
1. 객체는 논리 평가 시 `true`를 반환합니다. 단 하나의 예외도 없기 때문에 객체는 숫자형이나 문자형으로만 형 변환이 일어난다고 생각하시면 됩니다.
11-
2. 숫자형으로의 형 변환은 객체끼리 빼는 연산을 할 때나 수학 관련 함수를 적용할 때 일어납니다. 객체 `Date`(<info:date>챕터에서 다룰 예정임)끼리 차감하면(`date1 - date2`) 두 날짜의 시간 차이가 반환됩니다.
12-
3. 문자형으로의 형 변환은 대게 `alert(obj)`같이 객체를 출력하려고 할 때 일어납니다.
10+
1. 객체는 논리 평가 시 `true`를 반환합니다. 단 하나의 예외도 없죠. 따라서 객체는 숫자형이나 문자형으로만 형 변환이 일어난다고 생각하시면 됩니다.
11+
2. 숫자형으로의 형 변환은 객체끼리 빼는 연산을 할 때나 수학 관련 함수를 적용할 때 일어납니다. 객체 `Date`끼리 차감하면(`date1 - date2`) 두 날짜의 시간 차이가 반환됩니다. `Date`에 대해선 <info:date>에서 다룰 예정입니다.
12+
3. 문자형으로의 형 변환은 대개 `alert(obj)`같이 객체를 출력하려고 할 때 일어납니다.
1313

1414
## ToPrimitive
1515

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

18-
객체 형 변환은 세종류로 구분되는데, 'hint'라 불리는 값이 구분 기준이 됩니다. "hint"가 무엇인지는 [명세](https://tc39.github.io/ecma262/#sec-toprimitive)에 자세히 설명되어 있는데, '목표로 하는 자료형' 정도로 이해하시면 될 것 같습니다.
18+
객체 형 변환은 세종류로 구분되는데, 'hint'라 불리는 값이 구분 기준이 됩니다. 'hint'가 무엇인지는 [명세서](https://tc39.github.io/ecma262/#sec-toprimitive)에 자세히 설명되어 있는데, '목표로 하는 자료형' 정도로 이해하시면 될 것 같습니다.
1919

2020
`"string"`
2121
: `alert` 함수같이 문자열을 기대하는 연산을 수행할 때는(객체-문자형 변환), hint가 `string`이 됩니다.
@@ -44,9 +44,9 @@
4444
```
4545

4646
`"default"`
47-
: 연산자가 기대하는 자료형이 '확실치 않을 때' hint는 `default`되는데 이는 아주 드문 경우입니다.
47+
: 연산자가 기대하는 자료형이 '확실치 않을 때' hint는 `default`됩니다. 아주 드물게 발생합니다.
4848

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

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

@@ -58,7 +58,7 @@
5858
if (user == 1) { ... };
5959
```
6060

61-
크고 작음을 비교할 때 쓰이는 연산자 `<`, `>` 역시 피연산자에 문자형과 숫자형 둘 다를 허용하는데, 이 연산자들은 hint를 "number"로 고정합니다. hint가 "default"가 되는 일이 없죠. 이는 하위 호환성 때문에 정해진 규칙입니다.
61+
크고 작음을 비교할 때 쓰이는 연산자 `<`, `>` 역시 피연산자에 문자형과 숫자형 둘 다를 허용하는데, 이 연산자들은 hint를 'number'로 고정합니다. hint가 'default'가 되는 일이 없죠. 이는 하위 호환성 때문에 정해진 규칙입니다.
6262

6363
실제 일을 할 때는 이런 사항을 모두 외울 필요는 없습니다. `Date` 객체를 제외한 모든 내장 객체는 hint가 `"default"`인 경우와 `"number"`인 경우를 동일하게 처리하기 때문입니다. 우리도 커스텀 객체를 만들 땐 이런 규칙을 따르면 됩니다.
6464

@@ -72,9 +72,9 @@ hint는 총 세 가지입니다. 아주 간단하죠.
7272
7373
1. 객체에 `obj[Symbol.toPrimitive](hint)`메서드가 있는지 찾고, 있다면 메서드를 호출합니다. `Symbol.toPrimitive`는 시스템 심볼로, 심볼형 키로 사용됩니다.
7474
2. 1에 해당하지 않고 hint가 `"string"`이라면,
75-
- `obj.toString()` `obj.valueOf()`를 호출합니다(존재하는 메서드만 실행됨).
75+
- `obj.toString()`이나 `obj.valueOf()`를 호출합니다(존재하는 메서드만 실행됨).
7676
3. 1과 2에 해당하지 않고, hint가 `"number"`나 `"default"`라면
77-
- `obj.valueOf()` `obj.toString()`을 호출합니다(존재하는 메서드만 실행됨).
77+
- `obj.valueOf()` `obj.toString()`을 호출합니다(존재하는 메서드만 실행됨).
7878
7979
## Symbol.toPrimitive
8080
@@ -86,7 +86,7 @@ obj[Symbol.toPrimitive] = function(hint) {
8686
};
8787
```
8888

89-
이제 실제 돌아가는 코드를 구현해 보도록 하겠습니다. `user` 객체에 객체-원시형 변환 메서드 `obj[Symbol.toPrimitive](hint)`구현해봅시다.
89+
실제 돌아가는 예시를 살펴보는 게 좋을 것 같네요. `user` 객체에 객체-원시형 변환 메서드 `obj[Symbol.toPrimitive](hint)`구현해보겠습니다.
9090

9191
```js run
9292
let user = {
@@ -114,15 +114,15 @@ alert(user + 500); // hint: default -> 1500
114114

115115
객체에 `Symbol.toPrimitive`가 없으면 자바스크립트는 아래 규칙에 따라 `toString`이나 `valueOf`를 호출합니다.
116116

117-
- hint가 'string'인 경우: `toString -> valueOf` (toString이 있다면 toString을 호출, toString이 없다면 valueOf를 호출함)
118-
- 그 외: `valueOf -> toString` (valueOf가 있다면 valueOf를 호출, valueOf가 없다면 toString을 호출함)
117+
- hint가 'string'인 경우: `toString -> valueOf` 순(`toString` 있다면 `toString` 호출, `toString` 없다면 `valueOf` 호출함)
118+
- 그 외: `valueOf -> toString`
119119

120120
이 메서드들은 반드시 원시값을 반환해야합니다. `toString`이나 `valueOf`가 객체를 반환하면 그 결과는 무시됩니다. 마치 메서드가 처음부터 없었던 것처럼 되어버리죠.
121121

122122
일반 객체는 기본적으로 `toString``valueOf`에 적용되는 다음 규칙을 따릅니다.
123123

124124
- `toString`은 문자열 `"[object Object]"`을 반환합니다.
125-
- `valueOf` 메서드는 객체 자신을 반환합니다.
125+
- `valueOf` 객체 자신을 반환합니다.
126126

127127
데모를 살펴봅시다.
128128

@@ -135,11 +135,11 @@ alert(user.valueOf() === user); // true
135135

136136
이런 이유 때문에 `alert`에 객체를 넘기면 `[object Object]`가 출력되는 것입니다.
137137

138-
여기서 `valueOf`를 언급하는 것은 튜토리얼의 완성도를 높이고 헷갈리는 것을 줄여주려는데 있습니다. 앞서 본 바와 같이 `valueOf`는 객체 자신을 반환하기 때문에 그 결과가 무시됩니다. 왜 그런거냐고 이유를 묻지는 말아주세요. 그냥 역사적인 이유때문입니다. 우리는 그냥 이 메서드가 존재하지 않는다고 생각하면 됩니다.
138+
여기서 `valueOf`튜토리얼의 완성도를 높이고 헷갈리는 것을 줄여주려고 언급했습니다. 앞서 본 바와 같이 `valueOf`는 객체 자신을 반환하기 때문에 그 결과가 무시됩니다. 왜 그런거냐고 이유를 묻지는 말아주세요. 그냥 역사적인 이유때문입니다. 우리는 그냥 이 메서드가 존재하지 않는다고 생각하면 됩니다.
139139

140140
이제 직접 이 메서드들을 사용한 예시를 구현해봅시다.
141141

142-
아래 예시의 `user``toString``valueOf`를 조합해 만들었는데, 위 예시에서 `Symbol.toPrimitive`를 사용한 것과 동일하게 동작합니다.
142+
아래 `user``toString``valueOf`를 조합해 만들었는데, `Symbol.toPrimitive`를 사용한 위쪽 예시와 동일하게 동작합니다.
143143

144144
```js run
145145
let user = {
@@ -184,24 +184,24 @@ alert(user + 500); // toString -> John500
184184

185185
## 반환 타입
186186

187-
위에 소개해드린 세 개의 메서드는 "hint"에 명시된 자료형으로의 형 변환을 보장해 주지 않습니다.
187+
위에서 소개해드린 세 개의 메서드는 'hint'에 명시된 자료형으로의 형 변환을 보장해 주지 않습니다.
188188

189189
`toString()`이 항상 문자열을 반환하리라는 보장이 없고, `Symbol.toPrimitive`의 hint가 `"number"`일 때 항상 숫자형 자료가 반환되리라는 보장이 없습니다.
190190

191191
확신할 수 있는 단 한 가지는 객체가 아닌 원시값을 반환해 준다는 것뿐입니다.
192192

193193
```smart header="과거의 잔재"
194-
`toString`이나 `valueOf`가 객체를 반환해도 에러가 발생하지 않습니다. 다만 이때는 반환 값이 무시되고, 메서드 자체가 존재하지 않았던 것처럼 동작합니다. 이렇게 동작하는 이유는 과거 자바스크립트엔 "에러"라는 개념이 잘 정립되어있지 않았기 때문입니다.
194+
`toString`이나 `valueOf`가 객체를 반환해도 에러가 발생하지 않습니다. 다만 이때는 반환 값이 무시되고, 메서드 자체가 존재하지 않았던 것처럼 동작합니다. 이렇게 동작하는 이유는 과거 자바스크립트엔 '에러'라는 개념이 잘 정립되어있지 않았기 때문입니다.
195195
196196
반면에 `Symbol.toPrimitive`는 *무조건* 원시자료를 반환해야 합니다. 그렇지 않으면 에러가 발생합니다.
197197
```
198198

199199
## 추가 형 변환
200200

201-
지금까지 살펴본 바와 같이 많은 수의 연산자와 함수는 피연산자의 형을 변환시킵니다. 곱셈을 해주는 연산자 `*`는 피연산자를 숫자형으로 변환시키죠.
201+
지금까지 살펴본 바와 같이 상당수의 연산자와 함수가 피연산자의 형을 변환시킵니다. 곱셈을 해주는 연산자 `*`는 피연산자를 숫자형으로 변환시키죠.
202202

203203
객체가 피연산자일 때는 다음과 같은 단계를 거쳐 형 변환이 일어납니다.
204-
1. 객체는 원시형으로 변화됩니다. 변환 규칙은 위에서 설명한 바 있습니다.
204+
1. 객체는 원시형으로 변화됩니다. 변환 규칙은 위에서 설명했습니다.
205205
2. 변환 후 원시값이 원하는 형이 아닌 경우엔 또다시 형 변환이 일어납니다.
206206

207207
예시:
@@ -217,8 +217,8 @@ let obj = {
217217
alert(obj * 2); // 4, 객체가 문자열 "2"로 바뀌고, 곱셈 연산 과정에서 문자열 "2"는 숫자 2로 변경됩니다.
218218
```
219219

220-
1. 곱셈 연산 `obj * 2`에선 객체가 원시형으로 변화되므로 문자열 `"2"`가 됩니다.
221-
2. 문자열은 숫자형으로 변환되므로 `"2" * 2``2 * 2`가 됩니다.
220+
1. `obj * 2`에선 객체가 원시형으로 변화되므로 `toString`에의해 `obj` 문자열 `"2"`가 됩니다.
221+
2. 곱셈 연산은 문자열은 숫자형으로 변환시키므로 `"2" * 2``2 * 2`가 됩니다.
222222

223223
그런데 이항 덧셈 연산은 위와 같은 상황에서 문자열을 연결합니다.
224224

@@ -241,14 +241,14 @@ alert(obj + 2); // 22("2" + 2), 문자열이 반환되기 때문에 문자열끼
241241
- `"number"` (수학 연산)
242242
- `"default"` (드물게 발생함)
243243

244-
연산자별로 어떤 hint가 적용되는지는 명세에서 찾아볼 수 있습니다. 연산자가 기대하는 피연산자를 "확신할 수 없을 땐" hint는 `"default"`가 됩니다. 이런 경우는 아주 드물지만 말이죠. 내장 객체는 대게 hint가 `"default"`이면, hint가 `"number"`때와 동일하게 처리합니다. 따라서 실무에선 hint가 `"default"`인 경우와 `"number"`인 경우를 합쳐서 처리할 때가 많습니다.
244+
연산자별로 어떤 hint가 적용되는지는 명세에서 찾아볼 수 있습니다. 연산자가 기대하는 피연산자를 '확신할 수 없을 때'에는 hint가 `"default"`가 됩니다. 이런 경우는 아주 드물게 발생합니다. 내장 객체는 대개 hint가 `"default"`일 때와 `"number"`때를 동일하게 처리합니다. 따라서 실무에선 hint가 `"default"`인 경우와 `"number"`인 경우를 합쳐서 처리하는 경우가 많습니다.
245245

246246
객체-원시형 변환엔 다음 알고리즘이 적용됩니다.
247247

248-
1. 객체에 `obj[Symbol.toPrimitive](hint)`메서드가 있는지 찾고, 있다면 메서드를 호출합니다.
248+
1. 객체에 `obj[Symbol.toPrimitive](hint)`메서드가 있는지 찾고, 있다면 호출합니다.
249249
2. 1에 해당하지 않고 hint가 `"string"`이라면,
250-
- `obj.toString()` `obj.valueOf()`를 호출합니다(존재하는 메서드만 실행됨).
250+
- `obj.toString()`이나 `obj.valueOf()`를 호출합니다.
251251
3. 1과 2에 해당하지 않고, hint가 `"number"``"default"`라면
252-
- `obj.valueOf()` `obj.toString()`을 호출합니다(존재하는 메서드만 실행됨).
252+
- `obj.valueOf()` `obj.toString()`을 호출합니다.
253253

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

0 commit comments

Comments
 (0)