Skip to content

Commit a62a1b0

Browse files
[프로토타입 상속] 번역 보완
1 parent cefa865 commit a62a1b0

File tree

1 file changed

+34
-34
lines changed
  • 1-js/08-prototypes/01-prototype-inheritance

1 file changed

+34
-34
lines changed

1-js/08-prototypes/01-prototype-inheritance/article.md

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22

33
개발을 하다 보면 기존에 있는 기능을 가져와 확장해야 하는 경우가 생깁니다.
44

5-
사람에 관한 프로퍼티와 메서드를 가진 `user`라는 객체가 있는데, `user`와 상당히 유사하지만 약간의 차이가 있는 `admin``guest` 객체를 만들어야 한다고 가정해 봅시다. 이때 `user`의 메서드를 복사하거나 다시 구현하지 않고 `user`에 약간의 기능을 얹어 `admin``guest` 객체를 만들 수 있을겁니다.
5+
사람에 관한 프로퍼티와 메서드를 가진 `user`라는 객체가 있는데, `user`와 상당히 유사하지만 약간의 차이가 있는 `admin``guest` 객체를 만들어야 한다고 가정해 봅시다. 이때 "`user`의 메서드를 복사하거나 다시 구현하지 않고 `user`에 약간의 기능을 얹어 `admin``guest` 객체를 만들 수 있지 않을까?"라는 생각이 들 겁니다.
66

7-
*프로토타입 상속(prototypal inheritance)* 은 이럴 때 사용할 수 있는 기능입니다.
7+
자바스크립트 언어의 고유 기능인 *프로토타입 상속(prototypal inheritance)* 을 이용하면 위와 같은 생각을 실현할 수 있습니다.
88

99
## [[Prototype]]
1010

11-
자바스크립트에서 객체는 명세서에서 명명한 `[[Prototype]]`이라는 숨김 프로퍼티를 가지고 있는데, 그 값은 `null`이거나 다른 객체에 대한 참조가 됩니다. 만약 다른 객체를 참조하고 있다면 참조 대상을 '프로토타입(prototype)'이라 부릅니다.
11+
자바스크립트의 객체는 명세서에서 명명한 `[[Prototype]]`이라는 숨김 프로퍼티를 갖습니다. 이 숨김 프로퍼티 값은 `null`이거나 다른 객체에 대한 참조가되는데, 다른 객체를 참조하는 경우 참조 대상을 '프로토타입(prototype)'이라 부릅니다.
1212

1313
![prototype](object-prototype-empty.svg)
1414

1515
프로토타입의 동작 방식은 '신비스러운'면이 있습니다. `object`에서 프로퍼티를 읽으려고 하는데 해당 프로퍼티가 없으면 자바스크립트는 자동으로 프로토타입에서 프로퍼티를 찾기 때문이죠. 프로그래밍에선 이런 동작 방식을 '프로토타입 상속'이라 부릅니다. 언어 차원에서 지원하는 편리한 기능이나 개발 테크닉 중 프로토타입 상속에 기반해 만들어진 것들이 많습니다.
1616

17-
`[[Prototype]]` 프로퍼티는 내부 프로퍼티이면서 숨김 프로퍼티이지만 개발자가 값을 설정할 수 있습니다.
17+
`[[Prototype]]` 프로퍼티는 내부 프로퍼티이면서 숨김 프로퍼티이지만 다양한 방법을 사용해 개발자가 값을 설정할 수 있습니다.
1818

19-
아래 예시처럼 특별한 이름인 `__proto__`을 사용하면 됩니다.
19+
아래 예시처럼 특별한 이름인 `__proto__`을 사용하면 값을 설정할 수 있습니다.
2020

2121
```js run
2222
let animal = {
@@ -31,13 +31,13 @@ rabbit.__proto__ = animal;
3131
*/!*
3232
```
3333

34-
```smart header="`__proto__``[[Prototype]]`용 getter/setter입니다."
35-
`__proto__``[[Prototype]]`*다릅니다*. `__proto__``[[Prototype]]`의 getter(획득자)/setter(설정자) 입니다.
34+
```smart header="`__proto__``[[Prototype]]`용 getter·setter입니다."
35+
`__proto__``[[Prototype]]`*다릅니다*. `__proto__``[[Prototype]]`의 getter(획득자)이자 setter(설정자) 입니다.
3636

37-
하위 호환성 때문에 `__proto__`여전히 쓸 순 있지만 비교적 근래에 작성된 스크립트에선 `__proto__`대신 함수 `Object.getPrototypeOf``Object.setPrototypeOf`을 써서 프로토타입을 획득(get)하거나 설정(set)합니다. 근래엔 왜 `__proto__`를 쓰지 않는지와 두 함수의 자세한 설명에 대해선 이어지는 챕터에서 다룰 예정입니다.
37+
하위 호환성 때문에 여전히 `__proto__`사용할 순 있지만 비교적 근래에 작성된 스크립트에선 `__proto__` 대신 함수 `Object.getPrototypeOf``Object.setPrototypeOf`을 써서 프로토타입을 획득(get)하거나 설정(set)합니다. 근래엔 왜 `__proto__`를 쓰지 않는지와 두 함수의 자세한 설명에 대해선 이어지는 챕터에서 다룰 예정입니다.
3838

39-
`__proto__`는 브라우저 환경에서만 지원하도록 자바스크립트 명세에서 규정하였는데,
40-
실상은 서버 사이드를 포함한 모든 호스트 환경에서 `__proto__`를 지원합니다. `[[Prototype]]`보다는 `__proto__`가 조금 더 직관적이어서 이해하기 쉬우므로, 본 튜토리얼에선 `__proto__`사용해 예시를 만들도록 하겠습니다.
39+
`__proto__`는 브라우저 환경에서만 지원하도록 자바스크립트 명세서에서 규정하였는데,
40+
실상은 서버 사이드를 포함한 모든 호스트 환경에서 `__proto__`를 지원합니다. `[[Prototype]]`보다는 `__proto__`가 조금 더 직관적이어서 이해하기 쉬우므로, 본 튜토리얼의 예시에선 `__proto__`사용하도록 하겠습니다.
4141
```
4242
4343
객체 `rabbit`에서 프로퍼티를 얻고싶은데 해당 프로퍼티가 없다면, 자바스크립트는 자동으로 `animal`이라는 객체에서 프로퍼티를 얻습니다.
@@ -65,15 +65,15 @@ alert( rabbit.jumps ); // true
6565

6666
`(*)`로 표시한 줄에선 `animal``rabbit`의 프로토타입이 되도록 설정하였습니다.
6767

68-
`(**)`로 표시한 줄에서 `alert` 함수가 `rabbit.eats` 프로퍼티를 읽으려 했는데, `rabbit``eats`라는 프로퍼티가 없습니다. 이때 자바스크립트는 `[[Prototype]]`이 참조하고 있는 객체인 `animal`에서 `eats`를 얻어냅니다(아래 그림을 밑에서부터 위로 살펴보세요).
68+
`(**)`로 표시한 줄에서 `alert` 함수가 `rabbit.eats` 프로퍼티를 읽으려 했는데, `rabbit``eats`라는 프로퍼티가 없습니다. 이때 자바스크립트는 `[[Prototype]]`이 참조하고 있는 객체인 `animal`에서 `eats`를 얻어냅니다. 아래 그림을 밑에서부터 위로 살펴보세요.
6969

7070
![](proto-animal-rabbit.svg)
7171

72-
이제 "`rabbit`의 프로토타입은 `animal`입니다.""`rabbit``animal`을 상속받는다."라고 할 수 있게 되었네요.
72+
이제 "`rabbit`의 프로토타입은 `animal`입니다." 혹은 "`rabbit``animal`을 상속받는다."라고 할 수 있게 되었습니다.
7373

74-
덕분에 `rabbit`에서도 `animal`에 구현된 유용한 프로퍼티와 메서드를 사용할 수 있게 되었습니다. 이렇게 프로토타입에서 상속받은 프로퍼티를 '상속 프로퍼티(inherited property)'라고 합니다.
74+
프로토타입을 설정해 준 덕분에 `rabbit`에서도 `animal`에 구현된 유용한 프로퍼티와 메서드를 사용할 수 있게 되었네요. 이렇게 프로토타입에서 상속받은 프로퍼티를 '상속 프로퍼티(inherited property)'라고 합니다.
7575

76-
`animal`에 정의된 메서드를 `rabbit`에서 호출해 봅시다.
76+
상속 프로퍼티를 사용해 `animal`에 정의된 메서드를 `rabbit`에서 호출해 봅시다.
7777

7878
```js run
7979
let animal = {
@@ -90,17 +90,17 @@ let rabbit = {
9090
__proto__: animal
9191
};
9292

93-
// 메서드 walk는 rabbit의 프로토타입인 animal에서 상속받음
93+
// 메서드 walk는 rabbit의 프로토타입인 animal에서 상속받았습니다.
9494
*!*
9595
rabbit.walk(); // 동물이 걷습니다.
9696
*/!*
9797
```
9898

99-
아래 그림과 같이 프로토타입(`animal`)에서 `walk`를 자동으로 상속받았기 때문에 `rabbit`에서도 `walk`를 호출할 수 있습니다.
99+
아래 그림과 같이 프로토타입(`animal`)에서 `walk`를 자동으로 상속받았기 때문에 `rabbit`에서도 `walk`를 호출할 수 있게 되었습니다.
100100

101101
![](proto-animal-rabbit-walk.svg)
102102

103-
프로토타입 체인은 위 예시보다 더 길어질 수도 있습니다.
103+
프로토타입 체인은 지금까지 살펴본 예시들보다 길어질 있습니다.
104104

105105
```js run
106106
let animal = {
@@ -124,7 +124,7 @@ let longEar = {
124124
*/!*
125125
};
126126

127-
// 메서드 walk는 프로토타입 체인에서 얻어옴
127+
// 메서드 walk는 프로토타입 체인을 통해 상속받았습니다.
128128
longEar.walk(); // 동물이 걷습니다.
129129
alert(longEar.jumps); // true (rabbit에서 상속받음)
130130
```
@@ -144,7 +144,7 @@ alert(longEar.jumps); // true (rabbit에서 상속받음)
144144

145145
프로퍼티를 추가, 수정하거나 지우는 연산은 객체에 직접 해야 합니다.
146146

147-
아래 예시에선 객체 `rabbit`에 메서드 `walk`를 직접 할당합니다.
147+
객체 `rabbit`에 메서드 `walk`를 직접 할당해 보겠습니다.
148148

149149
```js run
150150
let animal = {
@@ -171,7 +171,7 @@ rabbit.walk(); // 토끼가 깡충깡충 뜁니다.
171171

172172
![](proto-animal-rabbit-walk-2.svg)
173173

174-
한편, 접근자 프로퍼티(accessor property)는 setter 함수를 통해서 프로퍼티에 값을 할당하므로 이 규칙이 적용되지 않습니다. 접근자 프로퍼티에 값을 할당하는 것은 함수를 호출하는 것과 같기 때문입니다.
174+
그런데 접근자 프로퍼티(accessor property)는 setter 함수를 통해서 프로퍼티에 값을 할당하므로 이 규칙이 적용되지 않습니다. 접근자 프로퍼티에 값을 할당하는 것은 함수를 호출하는 것과 같기 때문입니다.
175175

176176
아래 예시에서 `admin.fullName`이 의도한 대로 잘 작동하는 것을 확인할 수 있습니다.
177177

@@ -200,23 +200,23 @@ alert(admin.fullName); // John Smith (*)
200200
admin.fullName = "Alice Cooper"; // (**)
201201
```
202202

203-
`(*)`로 표시한 줄에서 `admin.fullName`프로토타입에 있는 getter 함수를 실행시키고, `(**)`로 표시한 줄의 할당 연산은 프로토타입에 있는 setter 함수를 실행시킵니다.
203+
`(*)`로 표시한 줄에서 `admin.fullName`프로토타입(`user`)에 있는 getter 함수(`get fullName`)를 호출하고, `(**)`로 표시한 줄의 할당 연산은 프로토타입에 있는 setter 함수(`set fullName`)를 호출합니다.
204204

205205
## 'this'가 나타내는 것
206206

207-
위 예시를 보면서 "`set fullName(value)``this`의 값은 무엇이지?"라는 의문이 생길 수 있습니다. "프로퍼티 `this.name``this.surname`에 값을 쓰면 그 값이 `user`에 저장될까, 아니면 `admin`에 저장될까?"라는 의문도 생길 수 있죠.
207+
위 예시를 보면 "`set fullName(value)` 본문의 `this`엔 어떤 값이 들어가지?"라는 의문을 가질 수 있습니다. "프로퍼티 `this.name``this.surname`에 값을 쓰면 그 값이 `user`에 저장될까, 아니면 `admin`에 저장될까?"라는 의문도 생길 수 있죠.
208208

209-
답은 간단합니다. `this`는 프로토타입에 전혀 영향을 받지 않습니다.
209+
답은 간단합니다. `this`는 프로토타입에 영향을 받지 않습니다.
210210

211211
**메서드를 객체에서 호출했든 프로토타입에서 호출했든 상관없이 `this`는 언제나 `.` 앞에 있는 객체가 됩니다.**
212212

213213
`admin.fullName=`으로 setter 함수를 호출할 때, `this``user`가 아닌 `admin`이 되죠.
214214

215-
메서드가 많이 구현되어있는 중심 객체 하나를 만들고, 이 객체를 상속받는 다양한 객체를 구현하는 경우가 많기 때문에 이런 특징을 잘 알아두셔야 합니다. 상속받은 메서드를 사용하더라도 객체는 프로토타입이 아닌 자신의 상태를 수정합니다.
215+
객체 하나를 만들고 여기에 메서드를 많이 구현해 놓은 다음, 여러 객체에서 이 커다란 객체를 상속받게 하는 경우가 많기 때문에 이런 특징을 잘 알아두셔야 합니다. 상속받은 메서드를 사용하더라도 객체는 프로토타입이 아닌 자신의 상태를 수정합니다.
216216

217-
예시를 통해 좀 더 알아봅시다. '메서드 저장소' 역할을 하는 객체 `animal``rabbit`상속받고 있는 상황입니다.
217+
예시를 통해 좀 더 알아봅시다. '메서드 저장소' 역할을 하는 객체 `animal``rabbit`상속받게 해보겠습니다.
218218

219-
`rabbit.sleep()`을 호출하면 `this.isSleeping`이 객체 `rabbit`설정되겠죠.
219+
`rabbit.sleep()`을 호출하면 `this.isSleeping`이 객체 `rabbit`설정됩니다.
220220

221221
```js run
222222
// animal엔 다양한 메서드가 있습니다.
@@ -249,7 +249,7 @@ alert(animal.isSleeping); // undefined (프로토타입에는 isSleeping이라
249249

250250
`rabbit` 말고도 `bird`, `snake` 등이 `animal`을 상속받는다고 해봅시다. 이 객체들도 `rabbit`처럼 `animal`에 구현된 메서드를 사용할 수 있겠죠. 이때 상속받은 메서드의 `this``animal`이 아닌 실제 메서드가 호출되는 시점의 점(`.`) 앞에 있는 객체가 됩니다. 따라서 `this`에 데이터를 쓰면 `animal`이 아닌 해당 객체의 상태가 변화합니다.
251251

252-
결론을 말씀드리자면 메서드는 공유되지만, 객체의 상태는 공유되지 않습니다.
252+
메서드는 공유되지만, 객체의 상태는 공유되지 않는다고 결론 내릴 수 있습니다.
253253

254254
## for..in 반복문
255255

@@ -278,9 +278,9 @@ for(let prop in rabbit) alert(prop); // jumps, eats
278278
*/!*
279279
```
280280

281-
[obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty)를 이용하면 상속 프로퍼티를 순회 대상에서 제외할 수 있습니다. 이 내장 메서드는 `key`에 대응하는 프로퍼티가 상속 프로퍼티가 아니고 `obj`에 직접 구현되어있는 프로퍼티라면 `true`를 반환합니다.
281+
[obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty)를 이용하면 상속 프로퍼티를 순회 대상에서 제외할 수 있습니다. 이 내장 메서드는 `key`에 대응하는 프로퍼티가 상속 프로퍼티가 아니고 `obj`에 직접 구현되어있는 프로퍼티일 때 `true`를 반환합니다.
282282

283-
`obj.hasOwnProperty(key)`사용하면 아래 예시에서처럼 상속 프로퍼티를 걸러낼 수 있고, 상속 프로퍼티만을 대상으로 무언가를 할 수도 있습니다.
283+
`obj.hasOwnProperty(key)`응용하면 아래 예시에서처럼 상속 프로퍼티를 걸러낼 수 있고, 상속 프로퍼티만을 대상으로 무언가를 할 수도 있습니다.
284284

285285
```js run
286286
let animal = {
@@ -303,11 +303,11 @@ for(let prop in rabbit) {
303303
}
304304
```
305305

306-
위 예시의 상속 관계를 그림으로 나타내면 다음과 같습니다. `rabbit``animal`을, `animal``Object.prototype`을, `Object.prototype``null`상속받습니다(`animal`객체 리터럴 방식으로 선언하였기 때문에 `Object.prototype`를 상속받습니다).
306+
위 예시의 상속 관계를 그림으로 나타내면 다음과 같습니다. `rabbit``animal`을, `animal``Object.prototype`을, `Object.prototype``null`상속받고 있습니다. `animal``Object.prototype`를 상속받는 이유는 객체 리터럴 방식으로 선언하였기 때문입니다.
307307

308308
![](rabbit-animal-object.svg)
309309

310-
`for..in` 안에 쓰인 메서드 `hasOwnProperty` `Object.prototype.hasOwnProperty`에서 왔다는 것을 그림을 통해 알 수 있습니다.
310+
그림을 보면 `for..in` 안에서 사용한 메서드 `hasOwnProperty` `Object.prototype.hasOwnProperty`에서 왔다는 것을 확인할 수 있습니다.
311311

312312
엇? 그런데 상속 프로퍼티인 `eats`는 얼럿 창에 출력되는데, `hasOwnProperty`는 출력되지 않았습니다. 무슨 일이 있는 걸까요?
313313

@@ -322,9 +322,9 @@ for(let prop in rabbit) {
322322
## 요약
323323

324324
- 자바스크립트의 모든 객체엔 숨김 프로퍼티 `[[Prototype]]`이 있는데, 이 프로퍼티는 객체나 `null`을 가리킵니다.
325-
- `obj.__proto__`를 사용하면 프로토타입에 접근할 수 있습니다. `__proto__``[[Prototype]]`의 getter/setter로 쓰이는데, 요즘엔 잘 쓰지 않습니다. 자세한 사항은 뒤쪽 챕터에서 다룰 예정입니다.
326-
- `[[Prototype]]`이 참조하는 객체는 '프로토타입'이라 부릅니다.
327-
- `obj`에서 프로퍼티를 읽거나 메서드를 호출하려 하는데 해당하는 프로퍼티나 메서드가 없으면 자바스크립트는 프로토타입에서 프로퍼티나 메서드를 찾습니다.
325+
- `obj.__proto__`를 사용하면 프로토타입에 접근할 수 있습니다. `__proto__``[[Prototype]]`의 getter·setter로 쓰이는데, 요즘엔 잘 쓰지 않습니다. 자세한 사항은 뒤쪽 챕터에서 다룰 예정입니다.
326+
- `[[Prototype]]`이 참조하는 객체를 '프로토타입'이라고 합니다.
327+
- `obj`에서 프로퍼티를 읽거나 메서드를 호출하려는데 해당하는 프로퍼티나 메서드가 없으면 자바스크립트는 프로토타입에서 프로퍼티나 메서드를 찾습니다.
328328
- 접근자 프로퍼티가 아닌 데이터 프로퍼티를 다루고 있다면, 쓰기나 지우기와 관련 연산은 프로토타입을 통하지 않고 객체에 직접 적용됩니다.
329329
- 프로토타입에서 상속받은 `method`라도 `obj.method()`를 호출하면 `method` 안의 `this`는 호출 대상 객체인 `obj`를 가리킵니다.
330330
- `for..in` 반복문은 객체 자체에서 정의한 프로퍼티뿐만 아니라 상속 프로퍼티도 순회 대상에 포함합니다. 반면, 키-값과 관련된 내장 메서드 대부분은 상속 프로퍼티는 제외하고 객체 자체 프로퍼티만을 대상으로 동작합니다.

0 commit comments

Comments
 (0)