1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
|
---
title: 객체 모델의 세부 사항
slug: Web/JavaScript/Guide/객체_모델의_세부사항
translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}</div>
<p class="summary">자바스크립트는 클래스 기반이 아닌 prototype에 기초한 객체 기반 언어 입니다. 이런 차이점으로 인해, 객체들의 계층 구조의 생성과 속성 및 속성 값의 상속을 어떻게 구현해야 하는지에 대한 부분이 덜 분명할 수 있습니다. 이번 장에서는 이런 상황을 명확하게 하고자 합니다. </p>
<p>이번 장에선 이미 자바스크립트를 어느 정도 알고 있고, 간단한 객체를 생성하는 함수들을 사용해보았다는 가정하에 진행합니다.</p>
<h2 id="클래스_기반_언어_대_프로토타입_기반_언어">클래스 기반 언어 대 프로토타입 기반 언어</h2>
<p>Java와 C++같은 클래스 기반의 언어들은 두개의 구별되는 개념에 기반을 두고 있습니다: 그건 바로 클래스와 인스턴스입니다.</p>
<ul>
<li>클래스는 특정 객체군을 특징 짓는 모든 속성들(Java에서는 메서드들과 필드들을 , C++에서는 멤버들을 속성으로 간주합니다. )을 정의합니다.클래스는 해당 객체군을 표현할 수 있는 특정 멤버를 지칭하는 것이 아닌 그보다 더 추상적인 것입니다. 예를 들어, <code>직원</code>클래스는 직원들을 대표할 수 있습니다.</li>
<li>반면 인스턴스는 클래스를 기반으로 실체화된 것입니다. 예를 들어, <code>빅토리아</code>는 특정 직원 개인을 나타내는 <code>직원</code>클래스의 인스턴스가 될 수 있습니다. 인스턴스는 부모 클래스의 속성과 동일한 속성들을 가집니다.</li>
</ul>
<p>자바스크립트같은 프로토타입기반의 언어들은 위와 같은 클래스와 인스턴스의 차이를 두지 않습니다. 간단하게 객체들을 가질 뿐입니다. prototype기반의 언어는 원형(프로토타입)의 객체 개념을 가지고 있습니다. 하나의 객체는 새로운 객체를 생성했을 때 초기 속성을 가질 수 있도록 하는 형판(template)으로 사용됩니다. 객체는 생성될 때 혹은 실행 시에 자기 자신의 속성을 명시할 수 있습니다. 추가적으로, 객체들은 또 다른 객체를 생성하기 위한 프로토타입으로 연관지어 질 수 있으며 프로토타입으로부터 생성된 두번째 객체가 프로토타입인 첫번째 객체의 속성을 공유(혹은 접근)하는 것을 허용합니다. </p>
<h3 id="클래스_정의">클래스 정의</h3>
<p>클래스 기반의 언어들에서, 별도의 클래스를 생성하고 그 안에서 해당 클래스를 정의 할 수 있습니다. 해당 정의에서 클래스의 인스턴스를 생성할 수 있는 생성자라고하는 특별한 메서드를 명시할 수 있습니다. 생성자는 해당 인스턴스의 초기 속성 값을 지정할 수 있고, 생성 시점에, 다른 적절한 처리를 수행 할 수 있습니다. 클래스의 인스턴스를 생성하기 위해서 new 연산자와 함께 생성자를 호출해야 합니다. </p>
<p>자바스크립트는 위와 비슷한 방법을 취합니다. 하지만 생성자이외에 따로 클래스 정의를 가지고 있지는 않습니다. 대신, 특정 속성및 속성값들을 가지고 객체를 생성하는 생성자 함수를 정의할 수 있습니다. 특정 자바스크립트 함수는 생성자로 사용 될 수 있습니다. 새로운 객체를 생성할려면 new연산자와 함께 생성자 함수를 사용해야 합니다.</p>
<div class="blockIndicator note">
<p>ECMAScript 2015에 <a href="/en-US/docs/Web/JavaScript/Reference/Classes">클래스 선언</a>이 새롭게 소개되었습니다.</p>
<blockquote>
<p>ECMAScript 2015에서 소개된 자바스크립트 클래스는 주로 문법적 설탕으로 기존 자바스크립트 프로토타입 기반 상속에 읽기 좋은 형식으로 바뀌었습니다. 이 클래스 문법이 자바스크립트에 새로운 객체 중심 상속 모델을 소개한 것은 아닙니다.</p>
</blockquote>
</div>
<h3 id="하위_클래스와_상속">하위 클래스와 상속</h3>
<p>클래스 기반 언어에서는 클래스 정의를 통해 클래스 계층구조를 생성합니다. 클래스를 정의할 때 이미 존재하는 클래스의 하위 클래스를 새로운 클래스로 지정할 수 있습니다. 이 하위 클래스는 부모 클래스의 모든 속성을 상속받으며 추가로 새로운 속성을 추가하거나 상속받은 속성을 수정할 수 있습니다. 예를 들어 이름(<code>name</code>)과 부서(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">dept</span></font>)을 가진 직원(<code>Employee</code>) 클래스와 그 하위 클래스에 보고(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">reports</span></font>) 속성을 추가한 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>) 클래스가 있다고 해봅시다. 이 경우 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>)의 인스턴스는 다음과 같이 세가지 속성을 모두 가질 수 있습니다 - 이름(<code>name</code>), 부서(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">dept</span></font>), 보고(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">reports</span></font>).</p>
<p>자바스크립트는 생성자 함수와 프로토타입 객체를 연결해 상속을 구현합니다. 이런 식으로 직원(<code>Employee</code>) — 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>) 예제를 똑같이 구현할 수 있지만 조금 다른 * 사용합니다. 먼저, 이름(<code>name</code>), 부서(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">dept</span></font>) 속성을 명시하여 직원(<code>Employee</code>) 생성자 함수를 정의합니다. 그런 다음, 직원(<code>Employee</code>)의 생성자를 호출한 후 보고(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">reports</span></font>) 속성을 명시해 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>) 생성자 함수를 정의합니다. 마지막으로 <code>Employee.prototype</code> 에서 파생된 새로운 객체를 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>) 생성자 함수의 프로토타입으로 지정합니다. 그런 다음 새로운 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>)를 만들면 관리자(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Manager</span></font>) 객체를 직원(<code>Employee</code>) 객체로부터 이름(<code>name</code>), 부서(<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">dept</span></font>) 속성을 상속받습니다. </p>
<h3 id="속성의_추가_삭제">속성의 추가 삭제</h3>
<p>클래스 기반의 언어들에서는, 일반적으로 컴파일 시점에 클래스를 생성한 후에 컴파일 시점 혹은 실행 시에 해당 클래스의 인스턴스를 생성합니다. 클래스가 한번 정의된 후에 클래스를 다시 컴파일 하지 않는다면, 속성의 갯수나 형식을 변경할 수 없습니다. 하지만 자바스크립트에서느 실행 시에 객체의 속성을 추가 혹은 삭제 할 수 있습니다. 만약 객체군의 프로토타입으로 사용되는 객체에 속성을 추가하면, 프로토타입이 되는 객체들에도 새로운 속성이 추가가 됩니다.</p>
<h3 id="차이점들에_대한_정리">차이점들에 대한 정리</h3>
<p>다음 표는 이런 차이점들에 대한 간략한 요약을 포함하고 있습니다. 이번 장의 다음 내용들은 객체의 계층 구조를 생성하기 위한 자바스크립트 생성자와 프로토타입들의 사용에 대한 세부 사항에 대해 기술합니다. 그리고 동일한 작업을 자바에서 어떻게 처리해야 하는지도 비교해서 살펴보겠습니다.</p>
<table class="standard-table">
<caption>클래스 기반(자바)과 프로토타입(prototype)기반(자바스크립트) 객체 시스템의 비교</caption>
<thead>
<tr>
<th scope="col">클래스 기반(자바)</th>
<th scope="col">원형 기반(자바스크립트)</th>
</tr>
</thead>
<tbody>
<tr>
<td>클래스와 인스턴스는 별개입니다.</td>
<td>모든 객체는 다른 객체로부터 상속을 받습니다.</td>
</tr>
<tr>
<td>클래스 정의를 가지고 클래스를 생성하고 생성자 메서드로 인스턴스를 생성합니다.</td>
<td>생성자 함수를 가지고 객체군을 정의 및 생성합니다.</td>
</tr>
<tr>
<td>new 연산자로 하나의 객체(인스턴스)를 생성합니다.</td>
<td>동일합니다.</td>
</tr>
<tr>
<td>이미 존재하는 클래스에 대한 하위 클래스를 정의함으로써 객체의 계층구조를 생성합니다.</td>
<td>하나의 객체를 생성자 함수와 결합된 프로토타입에 할당함으로써 객체의 계층구조를 생성 합니다.</td>
</tr>
<tr>
<td>클래스의 상속 구조에 따라 속성을 상속 받습니다.</td>
<td>프로토타입 체인에 따라 속성을 상속 받습니다.</td>
</tr>
<tr>
<td>클래스 정의는 모든 인스턴스의 모든 속성을 명시합니다. 실행시에 동적으로 속성을 추가할 수 없습니다.</td>
<td>생성자 함수 혹은 프로토타입은 초기 속성들을 명시합니다. 개별 객체 혹은 전체 객체군에 동적으로 속성을 추가 삭제할 수 있습니다.</td>
</tr>
</tbody>
</table>
<h2 id="직원_예제">직원 예제</h2>
<p>이장의 나머지 부분에서는 다음과 같은 직원 객체의 계층구조를 사용합니다. </p>
<div class="twocolumns">
<p>직원 객체의 계층 구조.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/3060/figure8.1.png"></p>
<ul>
<li>직원(<code>Employee</code>) 객체는 빈 문자열을 기본값으로 가지는 이름(<code>name</code>) 그리고 "일반(general)"을 기본 값으로 가지는 부서(<code>dept</code>)를 속성으로 가집니다.</li>
<li><font face="Consolas, Liberation Mono, Courier, monospace">관리자(</font><code>Manager</code>)객체는 직원(<code>Employee</code>) 객체를 근간으로 하며, 직원 객체들을 포함하기 위한 빈 배열을 기본 값으로 하는 보고(<code>reports</code>)속성을 가지고 있습니다.</li>
<li>근로자(<code>WorkerBee</code>)객체 또한 직원(<code>Employee</code>) 객체를 근간으로 하며, 문자열들을 포함하기 위한 빈 배열을 기본 값으로 하는 프로젝트(<code>projects</code>)속성을 가집니다.</li>
<li>영업사원(<code>SalesPerson</code>)객체는 또한 근로자(<code>WorkerBee</code>) 객체를 근간으로 하며, 100을 기본값으로 하는 할당량(<code>quota</code>)를 속성으로 가집니다. 또한 같은 부서내의 모든 영업사원을 지칭하기 위한 부서 속성을 "판매부서"로 재정의 합니다. </li>
<li>엔지니어(<code>Engineer</code>)객체도 근로자(<code>WorkerBee</code>) 객체를 근간으로 하며, 빈 문자열을 기본값으로 가지는 장비(<code>machine</code>) 속성을 가집니다.그리고 엔지니어링(engineering)이라는 값으로 부서 속성을 재정의 합니다.</li>
</ul>
</div>
<h2 id="계층_구조_생성">계층 구조 생성</h2>
<p>직원 계층 구조를 구현하기 위한 적절한 생성자 함수를 정의하는 방법에는 여러가지가 있습니다. 개발하려고 하는 어플리케이션에 따라 생성자 함수를 정의 하는 방법은 달라질 수 있습니다. </p>
<p>이번 절에서는 상속을 구현하기 위한 간단한 (비교적 유연하지는 않은) 정의 방법을 보여 줄 것입니다. 이런 정의 방법을 사용하게되면, 객체를 생성할 때 어떤 속성 값도 지정을 할 수 없습니다. 새로이 생성된 객체들은 기본값들을 가지고 있으며, 나중에 해당 속성 값들을 변경할 수 있습니다.</p>
<p>실제 어플리케이션에서는, 객체를 생성할때, 해당 객체가 가져야할 속성을 인자로 받는 생성자를 정의 할수 있습니다.(보다 자세한 사항은 다음을 참조하세요. <a href="#More_flexible_constructors">More flexible constructors</a>). 지금 당장은, 상속이 어떻게 작동하는지를 보여주기 위한 간단한 예제를 사용합니다. </p>
<p>다음의 자바와 자바스크립트로 작성된 직원 정의는 비슷합니다. 차이점은 자바언어에서는 개별 속성에 대한 타입(type)을 일일이 지정을 해야 하지만 자바스크립트에서는 일일이 개별 속성에 대한 타입(type)을 지정할 필요가 없다는 것입니다.(이런 이유로 자바스크립트가 약하게 형식화된 언어로 불리는 반면 자바는 <a href="http://en.wikipedia.org/wiki/Strong_and_weak_typing">강력하게 형식화된 언어</a>로 불립니다.)</p>
<table>
<tbody>
<tr>
<td>
<h4 id="자바스크립트">자바스크립트</h4>
<pre class="brush: js">
function Employee() {
this.name = "";
this.dept = "general";
}</pre>
</td>
<td>
<h4 id="자바">자바</h4>
<pre class="brush: java">
public class Employee {
public String name = "";
public String dept = "general";
}
</pre>
</td>
</tr>
</tbody>
</table>
<p>관리자와 근로자 정의는 계층 구조상에서 상위에 위치하는 객체를 어떻게 표시하는지에 대한 차이점을 보여 줍니다. 자바스크립트에서는 생성자 함수 정의 이후에 언제든 생성자 함수의 프로토타입(<code>prototype)</code> 속성의 값으로 프로토타입 인스턴스를 추가할 수 있습니다. 자바에서는 클래스 정의에 상위 클래스를 명시해야 합니다. 클래스 정의 이후에는 상위 클래스를 변경할 수 없습니다.</p>
<div class="twocolumns">
<h4 id="자바스크립트_2">자바스크립트</h4>
<pre class="brush: js">function Manager() {
Employee.call(this);
this.reports = [];
}
Manager.prototype = Object.create(Employee.prototype);
function WorkerBee() {
Employee.call(this);
this.projects = [];
}
WorkerBee.prototype = Object.create(Employee.prototype);
</pre>
<h4 id="자바_2">자바</h4>
<pre class="brush: java">public class Manager extends Employee {
public Employee[] reports = new Employee[0];
}
public class WorkerBee extends Employee {
public String[] projects = new String[0];
}
</pre>
</div>
<p>엔지니어와 영업사원 정의들은 객체들을 생성합니다. 생성된 객체는 근로자 객체의 하위 객체이고 따라서 직원 객체의 하위 객체가 됩니다. 상속 관계에 따라 엔지니어와 영업사원 객체들은 근로자와 직원객체의 속성을 가지게 됩니다. 게다가, 상속받은 부서 속성은 엔지니어와 영업사원에서 재정되어 새로운 값을 가지게 됩니다. </p>
<div class="twocolumns">
<h4 id="자바스크립트_3">자바스크립트</h4>
<pre class="brush: js">function SalesPerson() {
WorkerBee.call(this);
this.dept = "sales";
this.quota = 100;
}
SalesPerson.prototype = Object.create(WorkerBee.prototype);
function Engineer() {
WorkerBee.call(this);
this.dept = "engineering";
this.machine = "";
}
Engineer.prototype = Object.create(WorkerBee.prototype);
</pre>
<h4 id="Java">Java</h4>
<pre class="brush: java">public class SalesPerson extends WorkerBee {
public double quota;
public dept = "sales";
public quota = 100.0;
}
public class Engineer extends WorkerBee {
public String machine;
public dept = "engineering";
public machine = "";
}
</pre>
</div>
<p>이런 정의 방법을 통해, 기본값을 가지는 각각의 속성을 포함하는 객체의 인스턴스를 생성할 수 있습니다. 다음 그림은 새로운 객체를 생성하고 새로운 객체에 대한 속성값들을 보여 표시하기 위한 자바스크립트의 정의들을 보여 줍니다.</p>
<div class="note">
<p><strong>유의사항: </strong>클래스 기반 언어들에서 인스턴스라는 용어는 특정한 기술적 의미를 가지고 있습니다. 이러한 언어들에서, 하나의 인스턴스란 하나의 클래스의 개별적인 실체이며 클래스와는 근본적으로 다릅니다. 자바스크립트에서는 클래스와 인스턴스 간의 차이가 없기 때문에, "인스턴스"가 이런 기술적 의미를 갖지 않습니다. 하지만, 자바스크립트에 대해서 얘기하자면, 비공식적으로 "인스턴스"는 특정한 생성자 함수를 이용하여 생성된 오브젝트를 의미합니다. 그래서 이번 예제에서는 <code><code>jane</code></code>이 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: #eeeeee; font-size: 16px;"> Engineer </span></font>의 인스턴스라고 할 수 있습니다. 이와 유사하게, 부모, 자식, 상위, 하위의 용어들은 자바스크립트에서 공식적인 의미를 갖지 않습니다; 다만 프로토타입 체인 상의 상위 또는 하위 객체를 지칭하기 위해서 비공식적으로 사용할 수 있습니다.</p>
</div>
<h3 id="간단한_정의로_객체_생성">간단한 정의로 객체 생성</h3>
<div class="twocolumns">
<h4 id="객체의_계층구조">객체의 계층구조</h4>
<p>오른쪽에 보이는 코드로 생성된 객체의 계층 구조는 아래와 같습니다.</p>
<p><img src="https://mdn.mozillademos.org/files/10412/=figure8.3.png"></p>
<h4 id="개별_객체들">개별 객체들</h4>
<pre class="brush: js">var jim = new Employee;
// jim.name is ''
// jim.dept is 'general'
var sally = new Manager;
// sally.name is ''
// sally.dept is 'general'
// sally.reports is []
var mark = new WorkerBee;
// mark.name is ''
// mark.dept is 'general'
// mark.projects is []
var fred = new SalesPerson;
// fred.name is ''
// fred.dept is 'sales'
// fred.projects is []
// fred.quota is 100
var jane = new Engineer;
// jane.name is ''
// jane.dept is 'engineering'
// jane.projects is []
// jane.machine is ''
</pre>
</div>
<h2 id="객체_속성들">객체 속성들</h2>
<p>이번 장에서는 객체가 프로토타입체인 상의 다른 객체로부터 특성을 상속받는 방법과 런타임 상에서 프로퍼티를 추가하면 무슨 일이 일어나는 지 살펴봅니다.</p>
<h3 id="속성_상속">속성 상속</h3>
<p>아래 구문처럼 <code>WorkerBee</code> 생성자로 <code>mark</code> 객체를 생성했다고 가정합니다.</p>
<pre class="brush: js">var mark = new WorkerBee;
</pre>
<p>new 연산자를 만나면, 자바스크립트는 새로운 일반 객체를 생성하고 암묵적으로 내부의 [[Prototype]](<code>__proto__</code>) 속성의 값을 <code>WorkerBee.prototype</code> 의 값으로 할당하며, 해당 객체를 <code>this</code> 키워드의 값으로써 생성자 함수 <code>WorkerBee</code>에 전달합니다. 내부의 [[Prototype]] 속성은 속성값을 반환하기 위해 사용할 프로토타입 체인을 결정합니다. 이런 속성들이 할당되면, 자바스크립트는 새 객체를 반환하고, 할당 구문에 의해 변수 <code>mark</code>를 객체에 할당합니다.</p>
<p>이러한 절차는 <code>mark</code>가 프로토타입 체인으로부터 상속받는 속성의 값을 <code>mark</code> 객체 내부에(local values) 명시적으로 부여하진 않습니다. 당신이 속성의 값을 요청하면, 자바스크립트는 먼저 해당 객체에 값이 존재하는지 확인합니다. 존재한다면, 해당 값이 반환됩니다. 만약 해당 객체에 값이 없다면, 프로토타입 체인을 (내장 [[Prototype]] 속성;<code>__proto__</code>을 이용하여)확인합니다. 체인 상의 어떤 객체가 해당 속성의 값을 가지고 있다면 그 값이 반환됩니다. 그런 속성이 발견되지 않는다면, 자바스크립트는 객체가 속성을 가지고있지 않다고 할 것입니다. 이런 식으로, <code>mark</code> 객체는 다음의 속성과 값을 가집니다.</p>
<pre class="brush: js">mark.name = "";
mark.dept = "general";
mark.projects = [];</pre>
<p><code>mark</code> 객체는 <code>mark.__proto__</code>로 연결되어 있는 원형의 객체로부터 이름(<code>name</code>)과 부서(<code>dept</code>)에 대한 값을 상속 받습니다. 근로자(<code>WorkerBee</code>) 생성자로부터 <code>projects</code>속성에 대한 값을 할당을 받습니다.이것들이 자바스크립트내에서 속성과 속성 값의 상속입니다. 이런 과정의 몇몇 세부 사항들은 <a href="#Property_inheritance_revisited">Property inheritance revisited</a>에서 다룹니다. </p>
<p>이런 생성자들은 당신이 직접 인스턴스에만 해당 하는 값을 설정하도록 하지 않기때문에, 객체에 대한 이런 정보들은 일반적으로 적용됩니다. 근로자(<code>WorkerBee</code>)로부터 생성된 모든 새로운 객체들은 기본값이 적용된 속성 값들을 가지게 됩니다. 물론, 속성 값들을 변경할 수 있습니다. 아래처럼 특정 인스턴스에만 해당하는 값을 설정할 수 있습니다. </p>
<pre class="brush: js">mark.name = "Doe, Mark";
mark.dept = "admin";
mark.projects = ["navigator"];</pre>
<h3 id="속성_추가">속성 추가</h3>
<p>자바스크립트에선, 실행 시점에 특정 객체에 속성들을 추가 할 수 있습니다.생성자 함수가 제공하는 속성외에 다른 속성을 추가할 수 있습니다. 특정 단일 객체에 속성을 추가하기 위해선, 다음과 같이 해당 객체에 값을 할당 하면 됩니다:</p>
<pre class="brush: js">mark.bonus = 3000;
</pre>
<p>이렇게 하면 <code>mark</code>객체는 보너스(<code>bonus</code>)속성을 가지게 됩니다. 하지만 mark객체를 제외한 나머지 근로자<code>(WorkerBee)</code>객체들은 보너스 속성을 가지지 않습니다. </p>
<p>만약 생성자 함수의 원형으로 사용되는 객체에 새로운 속성을 추가한다면, 해당 프로토타입 객체(prototype)의 속성을 상속받는 모든 객체에 해당 속성이 추가됩니다. 예를 들면, 전문분야(<code>specialty</code>)속성을 모든 직원 객체에 다음과 같은 구문으로 추가할 수 있습니다:</p>
<pre class="brush: js">Employee.prototype.specialty = "none";
</pre>
<p>위의 구문을 실행한 직후, <code>mark</code>객체는 <code>"none"</code>이라는 값을 가지는 전문분야<code>(specialty)</code>속성을 가지게 됩니다.아래의 그림들은 해당 속성을 추가한 후 엔지니어<code>(Engineer)</code> 프로토타입에 대해 해당 속성을 재정의 했을 경우 각 객체에 미치는 영향을 보여줍니다.</p>
<p><img alt="" class="internal" src="/@api/deki/files/4422/=figure8.4.png" style="height: 519px; width: 833px;"><br>
<span style="font-size: 12px; line-height: 17px;"><strong>속성의 추가</strong></span></p>
<h2 id="좀_더_유연한_생성자들">좀 더 유연한 생성자들</h2>
<p>지금까지 살펴 본 생성자 함수들은 인스턴스를 생성하면서 동시에 속성값을 지정할 수 없었습니다. 자바의 경우, 인스턴스를 생성 시 생성자에 인자들을 넘겨주어 인스턴스의 속성들을 초기화 할 수 있습니다. 다음의 예제 그림들은 자바처럼 인스턴스 생성 시 속성값을 설정하는 방법을 보여줍니다.</p>
<p><img alt="" class="internal" id="figure8.5" src="/@api/deki/files/4423/=figure8.5.png" style="height: 481px; width: 1012px;"><br>
<small><strong>Specifying properties in a constructor, take 1</strong></small></p>
<p>다음의 표는 자바와 자바스크립트 각각의 생성자와 객체에 대한 정의를 보여 줍니다. </p>
<div class="twocolumns">
<h4 id="자바스크립트_4">자바스크립트</h4>
<h4 id="자바_3">자바</h4>
</div>
<div class="twocolumns">
<pre class="brush: js">function Employee (name, dept) {
this.name = name || "";
this.dept = dept || "general";
}
</pre>
<pre class="brush: java">public class Employee {
public String name;
public String dept;
public Employee () {
this("", "general");
}
public Employee (String name) {
this(name, "general");
}
public Employee (String name, String dept) {
this.name = name;
this.dept = dept;
}
}
</pre>
</div>
<div class="twocolumns">
<pre class="brush: js">function WorkerBee (projs) {
this.projects = projs || [];
}
WorkerBee.prototype = new Employee;
</pre>
<pre class="brush: java">public class WorkerBee extends Employee {
public String[] projects;
public WorkerBee () {
this(new String[0]);
}
public WorkerBee (String[] projs) {
projects = projs;
}
}
</pre>
</div>
<div class="twocolumns">
<pre class="brush: js">
function Engineer (mach) {
this.dept = "engineering";
this.machine = mach || "";
}
Engineer.prototype = new WorkerBee;
</pre>
<pre class="brush: java">public class Engineer extends WorkerBee {
public String machine;
public Engineer () {
dept = "engineering";
machine = "";
}
public Engineer (String mach) {
dept = "engineering";
machine = mach;
}
}
</pre>
</div>
<p>자바스크립트의 속성값을 설정하는 방법은 기본값을 설정하기 위한 관용구를 사용합니다.</p>
<pre class="brush: js">this.name = name || "";
</pre>
<p>자바스크립트의 OR 논리 연산자(<code>||</code>) 첫번째 인자를 평가합니다. 첫번째 인자가 참이면 첫번째 인자를 반환하고 그렇지 않은 경우는 두번째 인자를 반환합니다. 그러므로, 위의 코드는 <code>name</code>인자가 <code>name</code> 속성에 사용 가능한 값을 가지고 있는지 확인합니다. 확인 결과 <code>name</code>속성에 사용가능한 값을 가지고 있을 경우, 해당 값을 <code>this.name</code>에 설정하게 됩니다. 반대로 그렇지 않은 경우는 빈 문자열을 <code>this.name</code>에 설정합니다.얼핏 보면 헛갈리지만 보다 짧은 관용구를 사용하였습니다.</p>
<div class="note">
<p><strong>주의:</strong> 만약 인자로 false와 빈 문자열 값을 줄 경우 해당 구문은 예상한 대로 작동하지 않을 수 있습니다.</p>
</div>
<p>이런 정의들을 가지고, 객체의 인스턴스를 생성할때, 객체 자신만의 속성에 대한 값을 지정할 수 있습니다. 새로운 <code>Engineer</code>를 생성하기 위해서 다음과 같은 구문을 사용할 수 있습니다:</p>
<pre class="brush: js">var jane = new Engineer("belau");
</pre>
<p><code>Jane</code>의 속성들은 다음과 같습니다:</p>
<pre class="brush: js">jane.name == "";
jane.dept == "engineering";
jane.projects == [];
jane.machine == "belau"
</pre>
<p>위와 같은 코드 구문으로는 <code>name</code>과 같이 상속받은 속성에 대한 초기값을 지정할 수 없습니다.만약 상속 받은 속성의 초기값을 설정하고자 한다면, 생성자 함수의 코드를 변경해야 합니다.</p>
<p>지금까지, 원형 객체를 생성한 후, 그 새로운 객체 자신의 속성과 속성 값을 지정하는 것을 살펴 보았습니다. 프로토타입 체인상에서 해당 생성자가 상위 객체에 대한 생성자를 직접 호출 함으로써 더 많은 속성을 추가하도록 할 수 있습니다. 다음의 그림은 새로운 정의 방법을 보여 줍니다.</p>
<p><img alt="" class="internal" src="/@api/deki/files/4430/=figure8.6.png" style="height: 534px; width: 1063px;"><br>
<small><strong>생성자내에서 속성들 정의, 그림 2</strong></small></p>
<p>그럼 좀 더 상세하게 생성자 내에서 속성들을 정의하는 것을 살펴 보겠습니다. 다음은 엔지니어(<code>Engineer)</code> 생성자의 새로운 정의입니다:</p>
<pre class="brush: js">function Engineer (name, projs, mach) {
this.base = WorkerBee;
this.base(name, "engineering", projs);
this.machine = mach || "";
}
</pre>
<p>다음과 같이 새로운 엔지니어(<code>Engineer)</code>객체를 생성할 수 있습니다:</p>
<pre class="brush: js">var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
</pre>
<p>다음과 같은 순서에 따라 객체를 생성하고 속성을 정의하게 됩니다:</p>
<ol>
<li><code>new</code> 연산자는 프로토타입 객체를 생성하고 생성된 객체의 <code>__proto__</code>속성을 <code>Engineer.prototype</code>으로 설정합니다.</li>
<li><code>new</code> 연산자는 새로이 생성된 객체를 엔지니어<code>(Engineer)</code>생성자에 this 키워드의 값으로 전달합니다.</li>
<li>생성자는 생성한 객체에 대한 <code>base</code>라는 새로운 속성을 생성하고 근로자<code>(WorkerBee)</code> 생성자의 값을 base 속성에 할당합니다. 이런 과정은 근로자<code>(WorkerBee)</code> 생성자를 엔지니어<code>(Engineer)</code>객체의 메서드로 만듭니다. <code>base</code> 속성의 이름은 그리 특별하지 않습니다. 다른 어떤 속성명을 사용해도 무방합니다. <code>base</code> 속성명은 단지 해당 속성의 목적을 환기시키기 위한 것입니다.</li>
<li>
<p>생성자는 <code>base</code> 메서드에 필요한 인자들 (<code>"Doe, Jane"</code> and <code>["navigator", "javascript"]</code>)을 주어 호출합니다.명시적으로 생성자에서 사용한 <code>"engineering"</code>은 모든 엔지니어<code>(Engineer)</code>객체들이 상속받은 부서 속성에 대한 동일한 값을 가지며, 직원<code>(Employee)</code>으로부터 상속받은 값을 재정의 하는 것을 나타냅니다.</p>
</li>
<li><code>base</code>가 엔지니어<code>(Engineer)</code>의 메서드이기때문에 <code>base</code>메서드 내에서 <code>this</code>키워드를 스텝1에서 생성한 객체를 지칭하도록 해줍니다. 따라서, 근로자<code>(WorkerBee)</code> 함수는 차례대로 <code>"Doe, Jane"</code>과 <code>"engineering"</code> 인자를 직원<code>(Employee)</code>생성자에 전달합니다. 직원<code>(Employee)</code>생성자로부터 반환 시, 근로자<code>(WorkerBee)</code>함수는 남은 인자들을 프로젝트<code>(projects)</code>속성을 설정하기 위해 사용합니다. </li>
<li><code>base</code>메서드로부터 반환 시, 엔지니어<code>(Engineer)</code> 생성자는 해당 객체의 장비<code>(machine)</code>속성을 "belau"로 초기화 합니다.</li>
<li>생성자로부터 반환 시, 새롭게 생성된 객체를 <code>jane</code>변수에 할당 합니다.</li>
</ol>
<p>엔지니어(<code>Engineer</code>) 생성자내에서 근로자(<code>WorkerBee</code>)생성자를 호출하면, 엔지니어(<code>Engineer</code>)에 대한 상송을 적절하게 설정할 수 도 있을 것이라고 생각할 수 있을 것입니다.하지만 그렇지 않습니다. 근로자(<code>WorkerBee</code>)생성자를 호출하는 것은 엔지니어<code>(Engineer)</code>객체로 하여금 호출되는 모든 생성자 함수내에서 열거된 속성들을 가지고도록 보장합니다.그러나, 나중에 직원<code>(Employee)</code>혹은 근로자<code>(WorkerBee)</code> 원형에 속성을 추가한다면, 엔지니어<code>(Engineer)</code>객체에 의해 추가된 속성들은 상속이 되지 않습니다. 예를 들어, 아래와 같은 구문을 작성하였다고 가정합니다:</p>
<pre class="brush: js">function Engineer (name, projs, mach) {
this.base = WorkerBee;
this.base(name, "engineering", projs);
this.machine = mach || "";
}
var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
Employee.prototype.specialty = "none";
</pre>
<p><code>jane</code>객체는 전문분야<code>(specialty)</code>속성을 상속받지 않습니다.</p>
<pre class="brush: js">function Engineer (name, projs, mach) {
this.base = WorkerBee;
this.base(name, "engineering", projs);
this.machine = mach || "";
}
Engineer.prototype = new WorkerBee;
var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
Employee.prototype.specialty = "none";
</pre>
<p>이제 <code>jane</code>객체의 전문분야<code>(specialty)</code>속성은 "none"이 되었습니다.</p>
<p><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call" title="en-US/docs/JavaScript/Reference/Global Objects/Function/call">call()</a></code> 혹은 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" title="en-US/docs/JavaScript/Reference/Global Objects/Function/apply">apply()</a></code> 메서드를 사용는 것은 상속을 구현하는 또 다른 방법입니다. 다음의 두 예제는 동일한 결과를 보여줍니다. </p>
<div class="twocolumns">
<pre class="brush: js">function Engineer (name, projs, mach) {
this.base = WorkerBee;
this.base(name, "engineering", projs);
this.machine = mach || "";
}
</pre>
<pre class="brush: js">function Engineer (name, projs, mach) {
WorkerBee.call(this, name, "engineering", projs);
this.machine = mach || "";
}
</pre>
</div>
<p><code>base</code>를 사용하지 않고 구현을 하기 때문에, <code>call()</code> 메서드를 사용하여 상속을 구현하는 것이 보다 깔끔합니다.</p>
<h2 id="속성_상속의_재고">속성 상속의 재고</h2>
<p>이전 절에서 자바스크립트의 생성자와 원형(prototype)이 어떤 방식으로 상속과 객체의 계층 구조를 제공하는지를 살펴 보았습니다. 이번장에서는 이전 절에서 반드시 명백하게 짚고 넘어가지 않은 일부 미묘한 점들에 대해 살펴보겠습니다.</p>
<h3 id="객체_자신의_값과_상속받은_값">객체 자신의 값과 상속받은 값</h3>
<p>이번 장에서 이미 설명된 것 처럼, 객체의 속성에 접근할 때, 자바스크립트는 아래와 같은 절차를 따릅니다.</p>
<ol>
<li>해당 속성에 대한 객체 자신의 값이 있는지 확인하고 있으면 그 값을 반환한다.</li>
<li>객체 자신의 값이 없으면 <code>__proto__</code> 속성을 사용하여 프로토타입 체인을 확인한다.</li>
<li>프로토타입 체인상의 특정 객체가 해당 속성에 대한 값을 가지고 있다면 해당 객체의 값을 반환한다.</li>
<li>해당 속성을 가진 어떤 객체도 발견하지 못하면 해당 객체는 그 속성을 가지고 있지 않은 것으로 판단한다.</li>
</ol>
<p>이런 단계들의 결과는 생성자 및 프로토타입 체인등의 것들을 어떻게 정의 하느냐에 따라 달라집니다. 아래와 같은 원래의 예제는 이런 정의들을 가지고 있습니다:</p>
<pre class="brush: js">function Employee () {
this.name = "";
this.dept = "general";
}
function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
</pre>
<p>이런 정의들을 가지고, <code>amy</code>라는 근로자<code>(WorkerBee)</code>인스턴스를 아래와 같이 생성하였다고 가정합니다.</p>
<pre class="brush: js">var amy = new WorkerBee;
</pre>
<p><code>amy</code>객체는 프로젝트라는 자신만의 속성을 가집니다.이름과 부서 속성들은 <code>amy</code> 자신의 속성이 아닌 <code>amy</code>객체의 <code>__proto__</code>속성을 통해 가지고 온 속성들입니다. 따라서 <code>amy</code>는 이런 속성들의 값을 가지게 됩니다.</p>
<pre class="brush: js">amy.name == "";
amy.dept == "general";
amy.projects == [];
</pre>
<p>직원(<code>Employee)</code>과 연관되어 있는 프로토타입내의 이름 속성의 값을 아래와 같이 변경하였다고 가정합니다.</p>
<pre class="brush: js">Employee.prototype.name = "Unknown"
</pre>
<p>얼핏보기에, 새로운 값이 모든 직원 인스턴스에 적용이 될것으로 예상하겠지만 그렇지 않습니다. </p>
<p>직원 객체의 인스턴스를 생성할때, 해당 인스턴스는 이름 속성에 대해 자신이 가지고 있는 값(빈 문자열)을 취하게 됩니다.이것이 의미하는 것은 새로운 직원 객체를 생성하여 근로자(<code>WorkerBee)</code>의 프로토타입에 설정을 할때, <code>WorkerBee.prototype</code>이 이름 속성에 대한 자신만의 값을 가지고 있다는 것입니다.그러므로, <code>amy</code>객체(근로자 인스턴스)의 이름 속성에 대해 검색할때, <code>WorkerBee.prototype</code>내에서 이름 속성에 대한 <code>amy</code> 객체 자신의 값을 찾게됩니다. 그렇기때문에 <code>Employee.prototype</code>까지의 프로토타입 체인을 검색하지 않게 됩니다.</p>
<p>실행시에 객체의 속성 값을 변경하고 새로운 값이 모든 하위 객체들에게도 적용되도록 할려면, 객체의 생성자함수에서는 속성을 정의할 수 없습니다. 대신에, 생성자와 연결된 프로토타입에 추가할 수 있습니다. 예를 들어, 이전의 코드를 아래와 같이 변경하였다고 가정합니다:</p>
<pre class="brush: js">function Employee () {
this.dept = "general";
}
Employee.prototype.name = "";
function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
var amy = new WorkerBee;
Employee.prototype.name = "Unknown";
</pre>
<p>이 경우 <code>amy</code> 객체의 이름 속성의 값은 "Unknown"이 됩니다.</p>
<p>위의 예제에서처럼, 객체 생성 시에 객체의 속성에 대한 기본 값을 설정하고 실행 시에 해당 속성의 값을 변경하기를 원한다면, 해당 속성들을 생성자 함수 자체안에가 아닌 생성자의 프로토타입에 설정 하여야 합니다.</p>
<h3 id="인스턴스_관계_결정">인스턴스 관계 결정</h3>
<p>자바스크립트에서의 속성 검색은 객체 자신의 속성들을 먼저 살펴보고 해당 속성명을 찾지 못할 경우, 객체의 특별한 속성인 <code>__proto__</code>내에서 찾게 됩니다. 이런 검색은 재귀적으로 진행되며, 이런 과정을 "프로토타입 체인에서의 검색"이라고 합니다.</p>
<p>특별한 속성인 <code>__proto__</code>객체가 생성이 될때 설정이 됩니다.<code> __proto__</code>속성은 생성자의 프로토타입 속성의 값으로 설정이 됩니다. 따라서 <code>new Foo()</code> 표현식은 <code>__proto__ == <code class="moz-txt-verticalline">Foo.prototype</code></code><code class="moz-txt-verticalline">인 </code>객체를 생성합니다. 결과적으로 <code class="moz-txt-verticalline">Foo.prototype</code><code class="moz-txt-verticalline">의 속성들에 대한 변경은 </code><code>new Foo()</code> 표현식으로 생성한 모든 객체에 대한 속성 검색을 변경하게 됩니다.</p>
<p>모든 객체는 <code>__proto__</code>라는 객체 속성을 가집니다.(예외: <code>Object</code>). 모든 함수들은 <code>prototype</code>이라는 객체 속성을 가집니다. 따라서 객체들은 '프로토타입 상속'에 의해 다른 객체들과의 관계를 가지게 됩니다.객체의 <code>__proto__</code>속성과 함수의 <code>prototype </code>객체를 비교하여 상속을 테스트 해볼 수 있습니다. 자바스크립트는 특정 객체가 함수 <code>prototype</code>으로부터 상속 받는 객체일 경우 참<code>(true)</code>를 반환하는 <code>instanceof</code>라는 연산자를 제공합니다. 예를 들면,</p>
<pre class="brush: js">var f = new Foo();
var isTrue = (f instanceof Foo);</pre>
<p><a href="#Inheriting_properties">Inheriting properties</a>에 나오는 예제와 동일한 정의들을 작성해 놓았을 경우, 보다 상세한 예제는 아래와 같습니다.엔지니어(<code>Engineer)</code>객체를 아래와 같이 생성합니다:</p>
<pre class="brush: js">var chris = new Engineer("Pigman, Chris", ["jsd"], "fiji");
</pre>
<p>생성된 객체를 가지고 아래와 같은 구문을 실행할 경우 각 구문에 대한 결과는 모두 참(true)입니다.</p>
<pre class="brush: js">chris.__proto__ == Engineer.prototype;
chris.__proto__.__proto__ == WorkerBee.prototype;
chris.__proto__.__proto__.__proto__ == Employee.prototype;
chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
</pre>
<p>주어진 이런 상황에서, <code>instanceOf</code>를 다음과 같이 <font face="Consolas, Liberation Mono, Courier, monospace">직접 작성할 수 있을 것입니다:</font></p>
<pre class="brush: js">function instanceOf(object, constructor) {
object = object.__proto__;
while (object != null) {
if (object == constructor.prototype)
return true;
if (typeof object == 'xml') {
return constructor.prototype == XML.prototype;
}
object = object.__proto__;
}
return false;
}
</pre>
<div class="note">
<p><strong>주의: </strong>위의 구현내용은 최신 버전의 자바스크립트에서 XML객체들이 표현되는 방법의 특질을 해결하기 위해 해당 객체의 타입이 "xml"인지 확인합니다. 핵심적인 세부 사항을 확인하려면 {{ bug(634150) }}를 참조하세요.</p>
</div>
<p>위의 instanceOf함수를 사용하면 아래의 표현들은 모두 참(true)입니다:</p>
<pre class="brush: js">instanceOf (chris, Engineer)
instanceOf (chris, WorkerBee)
instanceOf (chris, Employee)
instanceOf (chris, Object)
</pre>
<p>하지만 아래의 표현식은 거짓(false)가 됩니다:</p>
<pre class="brush: js">instanceOf (chris, SalesPerson)
</pre>
<h3 id="생성자내에서의_전역_정보">생성자내에서의 전역 정보</h3>
<p>생성자를 생성할때, 생성자내에서 전역 정보를 설정할 경우, 주의를 해야 합니다. 예를 들어, 각각의 새로운 직원에게 자동으로 고유한 ID값을 할당하기를 원한다고 했을 때, 다음과 같은 직원(<code>Employee</code>) 정의를 사용할 수 있을 것입니다:</p>
<pre class="brush: js">var idCounter = 1;
function Employee (name, dept) {
this.name = name || "";
this.dept = dept || "general";
this.id = idCounter++;
}
</pre>
<p>이런 정의 내용을 가지고, 새로운 직원을 생성했을 때, 생성자는 다음의 고유한 ID값을 새로운 직원객체에 할당하고 전역 ID 카운터를 증가 시킵니다. 따라서 다음과 같은 구문으로 각각의 객체를 생성한다면, 결과는 <code>victoria.id</code>는 1 그리고 <code>harry.id</code>는 2가 됩니다:</p>
<pre class="brush: js">var victoria = new Employee("Pigbert, Victoria", "pubs")
var harry = new Employee("Tschopik, Harry", "sales")
</pre>
<p>얼핏보면 괜찮아 보입니다. 하지만 이유를 불문하고 직원 객체가 생성될때마다 <code>idCounter</code>는 증가분을 가지게 됩니다.이번장에서 나온 예제에서처럼 전체 직원<code>(Employee)</code> 객체의 계층 구조를 생성하였다면, 프로토타입을 설정할때마다 직원 생성자는 매번 호출 됩니다.다음과 같은 코드를 작성하였다고 가정합니다:</p>
<pre class="brush: js">var idCounter = 1;
function Employee (name, dept) {
this.name = name || "";
this.dept = dept || "general";
this.id = idCounter++;
}
function Manager (name, dept, reports) {...}
Manager.prototype = new Employee;
function WorkerBee (name, dept, projs) {...}
WorkerBee.prototype = new Employee;
function Engineer (name, projs, mach) {...}
Engineer.prototype = new WorkerBee;
function SalesPerson (name, projs, quota) {...}
SalesPerson.prototype = new WorkerBee;
var mac = new Engineer("Wood, Mac");
</pre>
<p>여기서 생략된 정의가 <code>base</code>속성을 가지고 해당 생성자를 프로토타입 체인내의 상위 생성자들을 호출한닥고 좀 더 가정하면, 이런 경우, 생성된 <code>mac</code>객체의 <code>id</code>값은 5가 됩니다.</p>
<p>어플리케이셔네 따라, 카운터가 이렇게 추가적으로 증가된 것은 문제가 될 수도 그렇지 않을 수 도 있습니다. 카운터에 정확한 값이 설정되기를 원한다면, 사용가능한 해결적은 아래와 같은 생성자를 대신 사용하는 것입니다:</p>
<pre class="brush: js">function Employee (name, dept) {
this.name = name || "";
this.dept = dept || "general";
if (name)
this.id = idCounter++;
}
</pre>
<p>prototype으로 사용할 직원 인스턴스를 생성할 때, 생성자에 인자들을 주어선 안됩니다. 이 생성자 정의를 사용하여, 인자들을 주지 않을 경우, 생성자는 id에 값을 할당하지 않으며 카운터를 갱신하지 않습니다. 따라서, id값을 가지는 직원 객체에 대해, 반드시 해당 직원의 이름을 명시해야 합니다. 이 예제의 경우 <code>mac</code>인스턴스의 <code>id</code>값은 1이 됩니다.</p>
<h3 id="다중상속_금지">다중상속 금지</h3>
<p>몇몇 객체 지향언어들은 다중 상속을 허용합니다. 그것은, 관련이 없는 부모 객체들로 부터 속성들과 값들을 상속 받을 수 있는 것을 말합니다. 자바스크립트는 다중 상속을 지원하지 않습니다.</p>
<p>속성 값의 상속은 속성에 대한 값을 찾기 위한 프로토타입 체인을 검색에 의해 실행 시점에 이루어 집니다. 하나의 객체는 오로지 하나의 결합된 prototype만을 가지기 때문에, 자바스크립트는 동적으로 하나 이상의 프로토타입 체인으로 부터 상속을 할 수 없습니다. </p>
<p>자바스크립트에서, 하나 이상의 다른 생성자 함수를 호출하는 생성자를 사용할 수 있습니다. 이것은 다중 상속처럼 보여질 수 있습니다. 예를 들어, 다음과 같은 구문들을 살펴보세요:</p>
<pre class="brush: js">function Hobbyist (hobby) {
this.hobby = hobby || "scuba";
}
function Engineer (name, projs, mach, hobby) {
this.base1 = WorkerBee;
this.base1(name, "engineering", projs);
this.base2 = Hobbyist;
this.base2(hobby);
this.machine = mach || "";
}
Engineer.prototype = new WorkerBee;
var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
</pre>
<p><code>WorkerBee</code>의 정의는 이번 장의 이전에 사용된 것과 동일하다고 가정합니다.이런 경우, <code>dennis</code>객체는 다음과 같은 속성들을 가지게 됩니다:</p>
<pre class="brush: js">dennis.name == "Doe, Dennis"
dennis.dept == "engineering"
dennis.projects == ["collabra"]
dennis.machine == "hugo"
dennis.hobby == "scuba"
</pre>
<p> 따라서 <code>dennis</code>객체는 <code>Hobbyist</code> 생성자로부터 <code>취미(hobby)</code>속성을 받아 오지 않습니다. 그런데 <code>Hobbyist</code>생성자의 프로토타입에 속성을 추가 했다고 가정하면 </p>
<pre class="brush: js">Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
</pre>
<p><code>dennis</code>객체는 새로이 추가된 속성을 상속받지 않습니다.</p>
<div>{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}</div>
|