aboutsummaryrefslogtreecommitdiff
path: root/files/de/web/javascript/guide/feinheiten_des_objektmodells/index.html
blob: 4d5e46ac26bc4914ada3b4ee67178177b59820f0 (plain)
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
715
716
717
718
719
720
721
---
title: Feinheiten des Objektmodells
slug: Web/JavaScript/Guide/Feinheiten_des_Objektmodells
tags:
  - Guide
  - Intermediate
  - JavaScript
  - Object
  - 'l10n:priority'
translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Mit_Objekten_arbeiten", "Web/JavaScript/Guide/Using_promises")}}</div>

<p class="summary">JavaScript ist eine Objektbasierte Programmiersprache, die auf Prototypen, statt auf Klassen basiert. Aufgrund dieser Tatsache ist es u. U. schwieriger zu erkennen, wie in JavaScript Objekthierarchien erstellt werden und die Vererbung von Eigenschaften und deren Werten erfolgt. Dieses Kapitel versucht diese Situation zu klären.</p>

<p>Dieses Kapitel geht davon aus, dass bereits Erfahrungen mit JavaScript vorhanden sind und man einfache Objekte mit Funktionen schon erstellt hat.</p>

<h2 id="Klassenbasierte_vs._Prototypbasierte_Sprachen">Klassenbasierte vs. Prototypbasierte Sprachen</h2>

<p>Klassenbasierte, Objektorientierte Sprachen wie Java und C++ bauen auf dem Konzept von Klassen und Instanzen auf.</p>

<ul>
 <li>Eine <em>Klasse</em> definiert alle Eigenschaften (was Methoden und Felder in Java oder Members in C++ entspricht), welche eine Menge von Objekten charakterisiert. Eine Klasse ist ein abstrakter Bauplan für Objekte. Die Klasse repräsentiert den Aufbau ihrer Objekte. Zum Beispiel kann die Klasse <code>Employee</code> die Menge aller Mitarbeiter repräsentieren.</li>
 <li>Eine <code>Instanz</code> ist auf der anderen Seite eine Instanz einer Klasse. Diese Instanz ist ein Mitglied der oben genannten Objektmenge. Zum Beispiel kann <code>Victoria</code> eine Instanz der <code>Employee</code> Klasse sein und somit einen individuellen Mitarbeiter repräsentieren. Eine Instanz hat genau die selben Eigenschaften wie die Elternklasse (keine mehr und keine weniger).</li>
</ul>

<p>Eine Prototypbasierte Sprache wie JavaScript hat diese Unterscheidung nicht: es gibt einfach Objekte. Eine Prototypbasierte Sprache hat die Notation eines <em>prototypischen Objektes</em>, ein Objekt welches als Template genutzt wird und die initialen Eigenschaften für ein neues Objekt vorgibt. Jedes Objekt kann seine eigenen Eigenschaften spezifizieren, entweder beim Erstellen oder zur Laufzeit. Zudem kann jedes Objekt als <em>Prototyp</em> für ein anderes Objekt verwendet werden, was es auch dem zweiten Objekt erlaubt seine Eigenschaften mit dem ersten Objekt zu teilen.</p>

<h3 id="Eine_Klasse_definieren">Eine Klasse definieren</h3>

<p>In einer Klassenbasierten Sprache definiert man Klassen in separaten <em>Klassendefinitionen</em>. In diesen Definitionen spezifiziert man spezielle Methoden, <em>Konstruktoren</em> genannt, um eine Instanz der Klasse zu erstellen. Eine Konstruktormethode spezifiziert Initialwerte für die Eigenschaften einer Instanz und kann andere Prozesse während der Erstellungszeit durchführen. Man benutzt den <code>new</code> Operator in Verbindung mit der Konstruktormethode, um Klasseninstanzen zu erstellen.</p>

<p>JavaScript folgt einem ähnlichen Modell, jedoch hat keine vom Konstruktor getrennte Klassendefinition. Stattdessen definiert man eine Konstruktorfunktion, um ein Objekt mit einer initialen Menge an Eigenschaften und Werten zu erstellen. Jede JavaScript Funktion kann als Konstruktor verwendet werden. Man benutzt den <code>new</code> Operator mit einer Konstruktorfunktion, um ein neues Objekt zu erstellen.</p>

<h3 id="Unterklassen_und_Vererbung">Unterklassen und Vererbung</h3>

<p>In einer Klassenbasierten Sprache erstellt man eine Hierarchie von Klassen durch die Klassendefinition. In der Klassendefinition kann man spezifizieren, dass die neue Klasse eine <em>Unterklasse</em> der schon existierenden Klassen ist. Die Unterklasse erbt alle Eigenschaften von der Oberklasse und kann neue Eigenschaften hinzufügen oder vererbte verändern. Angenommen die <code>Employee</code> Klasse hat nur die Eigenschaften <code>name</code> und <code>dept</code> und <code>Manager</code> ist eine Unterklasse von <code>Employee</code> welche die Eigenschaft <code>reports</code> hinzufügt. In diesem Fall hat eine Instanz der <code>Manager</code> Klasse alle drei Eigenschaften: <code>name</code>, <code>dept</code> und <code>reports</code>.</p>

<p>JavaScript implementiert Vererbung so, dass man jedes Prototypobjekt mit jeder Konstruktorfunktion verbinden kann. So kann man das gleiche <code>Employee</code><code>Manager</code> Beispiel erstellen, jedoch mit einer leicht anderen Terminologie. Als erstes definiert man die <code>Employee</code> Konstruktorfunktion, welche die Eigenschaften <code>name</code> und <code>dept</code> spezifiziert. Als nächstes definiert man die <code>Manager</code> Konstruktorfunktion, ruft den <code>Employee</code> Konstruktor auf und spezifiziert die <code>reports</code> Eigenschaft. Letztlich weist man ein neues Objekt zu, welches von <code>Employee.prototype</code> stammt und als <code>prototype</code> für die <code>Manager</code> Konstruktorfunktion dient. Dann, wenn man einen neuen <code>Manager</code> erstellt, erbt dieser die Eigenschaften <code>name</code> und <code>dept</code> von dem <code>Employee</code> Objekt.</p>

<h3 id="Hinzufügen_und_Entfernen_von_Eigenschaften">Hinzufügen und Entfernen von Eigenschaften</h3>

<p>In Klassenbasierten Sprachen wird eine Klasse typischerweise zur Übersetzungszeit erstellt und Instanzen dieser Klasse werden zur Übersetzungs- oder Laufzeit instantiiert. Man kann die Anzahl oder die Typen von Eigenschaften einer Klasse nicht nach der Definition der Klasse verändern. In JavaScript kann man immer EIgenschaften während der Laufzeit zu Objekten hinzufügen oder von ihnen entfernen. Wenn eine Eigenschaft zu einem Objekt hinzugefügt wird, welches als Prototyp für andere Objekte fungiert, so bekommen die anderen Objekte auch diese neue Eigenschaft.</p>

<h3 id="Zusammenfassung_von_Unterschieden">Zusammenfassung von Unterschieden</h3>

<p>Die folgende Tabelle gibt eine kurze Zusammenfassung von einigen der Unterschiede. Der Rest des Kapitels beschreibt detailliert den Einsatz von JavaScript Konstruktoren und Prototypen, um eine Objekthierarchie zu erstellen und vergleicht dieses mit der Sprache Java.</p>

<table class="standard-table">
 <caption>Vergleich von Klassbasierten (Java) und Prototypebasierten (JavaScript) Objektsystemen</caption>
 <thead>
  <tr>
   <th scope="col">Klassenbasiert (Java)</th>
   <th scope="col">Prototypbasiert (JavaScript)</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>Klassen und Instanzen sind verschiedene Dinge.</td>
   <td>Alle Objekte können von anderen Objekt erben.</td>
  </tr>
  <tr>
   <td>Definieren einer Klasse mit einer Klassendefinition; Instantiieren eine Klasse mit Konstruktormethoden.</td>
   <td>Definieren und Erstellen einer Menge von Objekten mit Konstruktorfunktionen.</td>
  </tr>
  <tr>
   <td>Erstellt ein Objekt mit dem <code>new</code> Operator.</td>
   <td>Genauso.</td>
  </tr>
  <tr>
   <td>Konstruiert eine Objekthierarchie mit Klassendefinitionen, um Unterklasse aus existierenden Klassen zu definieren.</td>
   <td>Konstruiert eine Objekthierarchie, indem ein Objekt als Prototyp mit einer Konstruktorfunktion verbunden werden.</td>
  </tr>
  <tr>
   <td>Erbt Eigenschaften entlang der Klassenkette.</td>
   <td>Erbt Eigenschaften entlang der Prototypenkette.</td>
  </tr>
  <tr>
   <td>Klassendefinitionen spezifizieren <em>alle</em> Eigenschaften von allen Klasseninstanzen. Man kann keine Eigenschaften dynamisch zur Laufzeit hinzufügen.</td>
   <td>Konstruktorfunktionen oder Prototypen spezifizieren eine <em>initiale Menge</em> von Eigenschaften. Man kann Eigenschaften dynamisch zu individuellen Objekten hinzufügen oder entfernen oder zu einer Menge von Objekten.</td>
  </tr>
 </tbody>
</table>

<h2 id="Das_Mitarbeiter-Beispiel">Das Mitarbeiter-Beispiel</h2>

<p>Das restliche Kapitel benutzt die Mitarbeiterhierarchie, die in folgender Grafik dargestellt ist.</p>

<div style="display: table-row;">
<div style="display: table-cell; width: 350px; text-align: center; vertical-align: middle; padding: 10px;">
<p>Eine einfache Objekthierarchie mit den folgenden Objekten:</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/3060/figure8.1.png"></p>
</div>

<div style="display: table-cell; vertical-align: middle; padding: 10px;">
<ul>
 <li><code>Employee</code> (Mitarbeiter) hat die Eigenschafte <code>name</code> (die als Initialwert einen leerer String hat) und <code>dept</code> (Abteilung) (die als Initialwert "general" hat).</li>
 <li><code>Manager</code> basiert auf <code>Employee</code>. Er fügt die Eigenschaft <code>reports</code> (Berichte) hinzu (die als Initialwert ein leeres Array hat und für ein Array von <code>Employee</code>s vorgesehen ist).</li>
 <li><code>WorkerBee</code> (Arbeitsbiene) basiert ebenfalls auf <code>Employee</code>. Er fügt die Eigenschaft <code>projects</code> hinzu (die als Initialwert ein leeres Array hat und für ein Array von Strings vorgesehen ist).</li>
 <li><code>SalesPerson</code> (Verkäufer) basiert auf <code>WorkerBee</code>. Er fügt die Eigenschaft <code>quota</code> (Pensum) hinzu (die als Initialwert 100 hat). zudem überschreibt er die <code>dept</code> Eigenschaft mit dem Wert "sales", um anzudeuten, dass alle Verkäufer in der gleichen Abteilung sind.</li>
 <li><code>Engineer</code> (Ingenieur) basiert auf <code>WorkerBee</code>. Er fügt die Eigenschaft <code>machine</code> (Maschine) hinzu (die als Initialwert einen leeren String hat) und überschreibt die Eigenschaft <code>dept</code> mit dem Wert "engineering".</li>
</ul>
</div>
</div>

<h2 id="Erstellen_der_Hierarchie">Erstellen der Hierarchie</h2>

<p>Es gibt viele Wege, um angemessene Konstruktorfunktionen für die Mitarbeiterhierarchie zu implementieren. Welchen man auswählt hängt stark davon ab, was in der Anwendung erreicht werden soll.</p>

<p>Dieser Abschnitt zeigt, wie man eine sehr einfache (und vergleichbar unflexible) Definition benutzen kann, um zu demonstrieren, wie die Vererbung funktioniert. In dieser Definition ist es nicht möglich jeden Eigenschaftswert zu spezifizieren, wenn ein Objekt erstellt wird. Die neu erstellten Objekte bekommen nur die Initialwerte und können später verändert werden.</p>

<p>In einer echten Anwendung würde man Konstruktoren so definieren, dass man diesen Eigenschaftswerte zur Erstellzeit übergeben kann (siehe <a href="#Flexiblere_Konstruktoren">Flexiblere Konstruktoren</a> für mehr Informationen). Für den Anfang zeigen diese Definitionen wie die Vererbung funktioniert.</p>

<p>Die folgenden Java und JavaScript <code>Employee</code> Definitionen sind gleich. Der einzige Unterschied ist, dass in Java für jede Eigenschaft ein Typ definiert sein muss, in JavaScript jedoch nicht (das liegt daran, dass Java eine <a href="https://de.wikipedia.org/wiki/Starke_Typisierung">stark typisierte Sprache</a> ist, während JavaScript eine schwach typisierte Sprache ist).</p>

<div class="twocolumns">
<h4 id="JavaScript">JavaScript</h4>

<pre class="brush: js notranslate">function Employee() {
  this.name = '';
  this.dept = 'general';
}
</pre>

<h4 id="Java"><br>
 Java</h4>

<pre class="brush: java notranslate">public class Employee {
   public String name = "";
   public String dept = "general";
}
</pre>
</div>

<p>Die <code>Manager</code> und <code>WorkerBee</code> Definitionen zeigen die Unterschiede bei der Spezifizierung eines Oberobjektes in der Vererbungskette. In JavaScript fügt man eine Prototypinstanz der Eigenschaft <code>prototype</code> der Konstruktorfunktion hinzu. Man kann dieses zu jedem Zeitpunkt nach der Definition des Konstruktors machen. In Java spezifiziert man die Oberklasse in der Klassendefinition. Man kann die Oberklasse nicht außerhalb der Klassendefinition ändern.</p>

<div class="twocolumns">
<h4 id="JavaScript_2">JavaScript</h4>

<pre class="brush: js notranslate">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="Java_2"><br>
 Java</h4>

<pre class="brush: java notranslate">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>Die <code>Engineer</code> und <code>SalesPerson</code> Definition erstellt Objekte, welche von <code>WorkerBee</code> und somit auch von <code>Employee</code> abstammen. Ein Objekt von diesen Typen hat alle Eigenschaften der vorherigen Objekte in der Vererbungskette. Zudem überschreiben diese Definitionen den Wert der geerbten <code>dept</code> Eigenschaft mit einem neuen Wert für diese Objekte.</p>

<div class="twocolumns">
<h4 id="JavaScript_3">JavaScript</h4>

<pre class="brush: js notranslate">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_3"><br>
 Java</h4>

<pre class="brush: java notranslate">public class SalesPerson extends WorkerBee {
   public String dept = "sales";
   public double quota = 100.0;
}


public class Engineer extends WorkerBee {
   public String dept = "engineering";
   public String machine = "";
}

</pre>
</div>

<p>Mit diesen Definitionen kann man Instanzen dieser Objekte mit ihren Initialwerten und Eigenschaften erstellen. Die nächste Grafik zeigt diese JavaScript Definitionen, um neue Objekte zu erzeugen und die Werte der neuen Objekte.</p>

<div class="note">
<p><strong>Hinweis:</strong> Der Term <em>Instanz</em> hat eine spezielle technische Bedeutung in Klassenbasierten Sprachen. In diesen Sprachen ist eine Instanz eine individuelle Instanz von einer Klasse und ist fundamental anders als eine Klasse. In JavaScript gibt es diese technische Bedeutung nicht, weil JavaScript nicht zwischen Klassen und Instanzen unterscheidet. Immer wenn über JavaScript Instanzen gesprochen wird, ist das rein informell und bedeutet, dass ein Objekte mit einer Konstruktorfunktion erstellt wurde. So kann man in diesem Beispiel sagen, dass <code><code>jane</code></code> eine Instanz von <code><code>Engineer</code></code> ist. Ebenso haben die Terme <em>Eltern</em>, <em>Kind</em>, <em>Vorfahre</em><strong><em> </em></strong>und <em>Nachfahre</em> keine formale Bedeutung in JavaScript; Man kann diese benutzen, um deutlich zu machen wo sich ein Objekt in der Prototypenkette befindet.</p>
</div>

<h3 id="Objekte_mit_der_einfachen_Definition_erstellen">Objekte mit der einfachen Definition erstellen</h3>

<div class="twocolumns">
<h4 id="Objekthierarchie">Objekthierarchie</h4>

<p>Die folgende Hierarchie wird mit dem Code auf der rechten Seite erstellt.</p>

<p><img src="https://mdn.mozillademos.org/files/10412/=figure8.3.png"></p>

<h4 id="Individuelle_Objekte_Jim_Sally_Mark_Fred_Jane_etc._Instanzen_erstellt_vom_Konstruktor">Individuelle Objekte = Jim, Sally, Mark, Fred, Jane, etc.<br>
 "Instanzen" erstellt vom Konstruktor</h4>

<pre class="brush: js notranslate">var jim = new Employee;
// Parentheses can be omitted if the
// constructor takes no arguments.
// 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="Objekteigenschaften">Objekteigenschaften</h2>

<p>Dieser Abschnitt diskutiert, wie Objekte EIgenschaften von anderen Objekten in der Prototypenkette erben und was passiert, wenn eine Eigenschaft währende der Laufzeit hinzugefügt wird.</p>

<h3 id="Eigenschaften_vererben">Eigenschaften vererben</h3>

<p>Es wird vorausgesetzt, dass das Objekt <code>mark</code> als <code>WorkerBee</code> mit dem folgenden Statement erstellt wurde:</p>

<pre class="brush: js notranslate">var mark = new WorkerBee;
</pre>

<p>Wenn JavaScript den <code>new</code> Operator sieht, erstellt es ein neues generisches Objekt und setzt implizit den Wert der internen Eigenschaft [[Prototype]] auf den Wert <code>WorkerBee.prototype</code> und setzt die <em><code>this</code></em> Referenz in der <code>WorkerBee</code> Konstruktorfunktion auf das neu erstellte Objekt. Die interne [[Prototype]] Eigenschaft legt die Prototypenkette fest, die zum Zurückgeben von Eigenschaftswerten benutzt wird. Sobald diese Eigenschaften gesetzt sind, gibt JavaScript das neue Objekt zurück und das Zuweisungsstatement setzt die Variable <code>mark</code> mit diesem Objekt.</p>

<p>Dieser Prozess fügt keine Werte in das <code>mark</code>-Objekt (lokale Werte) für Eigenschaften, die <code>mark</code> von der Prototypenkette erbt. Wenn man nach einem Wert einer Eigenschaft fragt, prüft JavaScript erst, ob der Wert in dem Objekt existiert. Wenn dies der Fall ist, wird dieser zurückgegeben. Wenn kein lokaler Wert vorhanden ist, prüft JavaScript die Prototypenkette (über die interne [[Prototype]] Eigenschaft). Wenn ein Objekt in der Prototypenkette einen Wert für die Eigenschaft hat, wird diese zurückgegeben. Wenn keine solche Eigenschaft gefunden wird, geht JavaScript davon aus, dass das Objekt keine solche Eigenschaft hat. Dementsprechend hat das <code>mark</code> Objekt folgende Eigenschaften und Werte:</p>

<pre class="brush: js notranslate">mark.name = '';
mark.dept = 'general';
mark.projects = [];
</pre>

<p>Das <code>mark</code> Objekt hat lokale Werte für die <code>name</code> und <code>dept</code> Eigenschaft über den <code>Employee</code> Konstruktor zugewiesen bekommen. Es wurde ein Wert für die Eigenschaft <code>projects</code> vom <code>WorkerBee</code> Konstruktor zugewiesen. Dieses gibt die Vererbung von Eigenschaften und Werten in JavaScript her. Einige Feinheiten dieses Prozesses werden in <a href="#Eigenschaftsvererbung_erneut_besuchen">Eigenschaftsvererbung erneut besuchen</a> behandelt.</p>

<p>Weil diese Konstruktoren keine instanzspezifischen Werte bereitstellen können, sind diese Informationen generisch. Die Eigenschaftswerte sind die Standardwerte, die bei der Erstellung aller mit <code>WorkerBee</code> erstellten Objekt genutzt werden. Man kann natürlich die Werte jeder Eigenschaft ändern. So kann man spezifische Informationen für <code>mark</code> wie folgt vergeben:</p>

<pre class="brush: js notranslate">mark.name = 'Doe, Mark';
mark.dept = 'admin';
mark.projects = ['navigator'];</pre>

<h3 id="Eigenschaften_hinzufügen">Eigenschaften hinzufügen</h3>

<p>In JavaScript kann man zu jedem Objekt zur Laufzeit Eigenschaften hinzufügen. Man ist nicht nur auf die unterstützten Eigenschaften der Konstruktorfunktion angewiesen. Um eine Eigenschaft spezifisch zu einem einfachen Objekt hinzuzufügen, kann man diese wie folgt dem Objekt zuweisen:</p>

<pre class="brush: js notranslate">mark.bonus = 3000;
</pre>

<p>Jetzt hat das <code>mark</code> Objekt eine <code>bonus</code> Eigenschaft, aber kein anderer <code>WorkerBee</code> hat diese Eigenschaft.</p>

<p>Wenn man eine neue Eigenschaft zu einem Objekt hinzufügt, welches als Prototyp für eine Konstruktorfunktion benutzt wird, fügt man die Eigenschaft zu allen Objekten hinzu, die Eigenschaften von diesem Prototypen erben. Zum Beispiel kann man eine <code>specialty</code> Eigenschaft zu allen <code>employee</code>s mit dem folgenden Statement hinzufügen:</p>

<pre class="brush: js notranslate">Employee.prototype.specialty = 'none';
</pre>

<p>Nach der Ausführung dieses Statements durch JavaScript, hat das <code>mark</code> Objekt auch die <code>specialty</code> Eigenschaft mit dem Wert <code>"none"</code>. Die folgende Grafik zeigt den Effekt des Hinzufügens dieser Eigenschaft zum <code>Employee</code> Prototyp und das Überschreiben des <code>Engineer</code> Prototypen.</p>

<p><img alt="" class="internal" src="/@api/deki/files/4422/=figure8.4.png" style="height: 519px; width: 833px;"><br>
 <small><strong>Eigenschaften hinzufügen</strong></small></p>

<h2 id="Flexiblere_Konstruktoren">Flexiblere Konstruktoren</h2>

<p>Mit den bisher gezeigten Konstruktorfunktionen kann man beim Erstellen einer Instanz keine Eigenschaftswerte angeben. Wie bei Java kann man Konstruktoren Argumente zum Initialisieren von Eigenschaftswerten für Instanzen übergeben. Die folgende Abbildung zeigt eine Möglichkeit, dies zu tun.</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>Spezifizieren von Eigenschaften in einem Konstruktor, Teil 1</strong></small></p>

<p>Die folgende Tabelle zeigt die Java und JavaScript Definitionen für diese Objekte.</p>

<div class="twocolumns">
<h4 id="JavaScript_4">JavaScript</h4>

<h4 id="Java_4">Java</h4>
</div>

<div class="twocolumns">
<pre class="brush: js notranslate">function Employee(name, dept) {
  this.name = name || '';
  this.dept = dept || 'general';
}
</pre>

<pre class="brush: java notranslate">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 notranslate">function WorkerBee(projs) {

 this.projects = projs || [];
}
WorkerBee.prototype = new Employee;
</pre>

<pre class="brush: java notranslate">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 notranslate">
function Engineer(mach) {
   this.dept = 'engineering';
   this.machine = mach || '';
}
Engineer.prototype = new WorkerBee;
</pre>

<pre class="brush: java notranslate">public class Engineer extends WorkerBee {
   public String machine;
   public Engineer () {
      dept = "engineering";
      machine = "";
   }
   public Engineer (String mach) {
      dept = "engineering";
      machine = mach;
   }
}
</pre>
</div>

<p>Diese JavaScript Definitionen benutzen eine spezielle Syntax für das Setzen von Standardwerten:</p>

<pre class="brush: js notranslate">this.name = name || '';
</pre>

<p>Der logische ODER Operator (<code>||</code>) von JavaScript wertet das erste Argument aus. Wenn das Argument zu <code>true</code> konvertiert wird, gibt der Operator dieses zurück. Andernfalls wird der Wert des zweiten Arguments zurückgegeben. Demnach prüft diese Zeile Code, ob <code>name</code> einen nützlichen Wert für die <code>name</code> Eigenschaft hat. Wenn das der Fall ist, wird <code>this.name</code> auf diesen Wert gesetzt. Andernfalls wird <code>this.name</code> auf den leeren String gesetzt. Dieses Kapitel nutzt diese Syntax aus Gründen der Kürze; es kann jedoch auf den ersten Blick verwirrend sein.</p>

<div class="note">
<p><strong>Hinweis:</strong> Das kann möglicherweise nicht wie erwartet funktionieren, wenn der Konstruktorfunktion Argumente übergeben werden, welche zu <code><code>false</code></code> konvertiert werden (wie <code>0</code> (null) und der leere String (<code>""</code>)). In diesen Fällen wird der Standardwert benutzt.</p>
</div>

<p>Mit dieser Definition, kann man beim Erstellen einer Objektinstanz spezifische Werte für die lokal definierten Eigenschaften benutzen. Man kann das folgende Statement nutzen, um einen neuen <code>Engineer</code> zu erstellen:</p>

<pre class="brush: js notranslate">var jane = new Engineer('belau');
</pre>

<p><code>Jane</code>'s Eigenschaften sind jetzt:</p>

<pre class="brush: js notranslate">jane.name == '';
jane.dept == 'engineering';
jane.projects == [];
jane.machine == 'belau';
</pre>

<p>Zu beachten ist, dass man mit diesen Definitionen keinen Initialwert für vererbte Eigenschaft wie <code>name</code> spezifizieren kann. Wenn man einen Initialwert für vererbe Eigenschaften in JavaScript spezifizieren möchte, muss man mehr Code zum Konstruktor hinzufügen.</p>

<p>Bisher hat die Konstruktorfunktion ein generisches Objekt erstellt und dann lokale Eigenschaften und Werte für das neue Objekt angegeben. Man kann den Konstruktor weitere Eigenschaften hinzufügen lassen, indem Sie die Konstruktorfunktion für ein Objekt in der Prototypkette direkt aufrufen. Die folgende Abbildung zeigt diese neuen Definitionen.</p>

<p><img alt="" class="internal" src="/@api/deki/files/4430/=figure8.6.png" style="height: 534px; width: 1063px;"><br>
 <small><strong>Spezifizieren von Eigenschaften in einem Konstruktor, Teil 2</strong></small></p>

<p>Sehen wir uns eine dieser Definitionen genauer an. Hier ist die neue Definition für den <code>Engineer</code>-Konstruktor:</p>

<pre class="brush: js notranslate">function Engineer(name, projs, mach) {
  this.base = WorkerBee;
  this.base(name, 'engineering', projs);
  this.machine = mach || '';
}
</pre>

<p>Angenommen, man erstellt ein neues <code>Engineer</code>-Objekt wie folgt:</p>

<pre class="brush: js notranslate">var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau');
</pre>

<p>JavaScript folgt folgenden Schritten:</p>

<ol>
 <li>Der <code>new</code> Operator erstellt ein generisches Objekt und setzt die <code>__proto__</code> EIgenschaft auf <code>Engineer.prototype</code>.</li>
 <li>Der <code>new</code> Operator übergibt das neue Objekt dem <code>Engineer</code> Konstruktor als Wert des <code>this</code> Schlüsselwortes.</li>
 <li>Der Konstruktor erstellt eine neue Eigenschaft namens <code>base</code> für dieses Objekt und weist dieser den Wert des <code>WorkerBee</code> Konstruktors zu. Das macht den <code>WorkerBee</code> Konstruktor zu einer Methode des <code>Engineer</code> Objektes. Der Name der <code>base</code> Eigenschaft ist nicht festgelegt. Man kann jeden legalen Eigenschaftsnamen nutzen; <code>base</code> erinnert einfach an den Zweck.</li>
 <li>Der Konstruktor ruft die <code>base</code> Methode auf, übergibt als Argumente zwei der Argumente des Konstruktors (<code>"Doe, Jane"</code> und <code>["navigator", "javascript"]</code>) und zudem den String <code>"engineering"</code>. Der explizite Einsatz von <code>"engineering"</code> im Konstruktor zeigt, dass alle <code>Engineer</code> Objekte den selben Wert für dei geerbte <code>dept</code> Eigenschaft haben und dieser Wert den vererbten Wert von <code>Employee</code> überschreibt.</li>
 <li>Weil <code>base</code> eine Methode von <code>Engineer</code> ist, weshalb JavaScrip beim Aufruf von <code>base</code> das Schlüsselwort <code>this</code> an das erstellte Objekt aus Schritt 1 bindet. Somit übergibt die <code>WorkerBee</code> Funktion die <code>"Doe, Jane"</code> und <code>"engineering"</code> Argumente zu der <code>Employee</code> Konstruktorfunktion. Nach der Rückgabe der <code>Employee</code> Konstruktorfunktion verwendet die <code>WorkerBee</code> Funktion das restliche Argument, um die <code>projects</code> Eigenschaft zu setzen.</li>
 <li>Nach der Rückgabe der <code>base</code> Methode initialisiert der <code>Engineer</code> Konstruktor die Objekteigenschaft <code>machine</code> mit <code>"belau"</code>.</li>
 <li>Nach der Rückgabe des Konstruktors weist JavaScript das neue Objekte, der <code>jane</code> Variablen zu.</li>
</ol>

<p>Man kann denken, dass man, nachdem der <code>WorkerBee</code>-Konstruktor innerhalb des <code>Engineer</code>-Konstruktors aufgerufen wird, die Vererbung für das <code>Engineer</code>-Objekte entsprechend eingerichtet hat. Das ist nicht der Fall. Der Aufruf des <code>WorkerBee</code> Konstruktors stellt sicher, dass ein <code>Engineer</code> Objekt mit den Eigenschaften beginnt, die in allen aufgerufenen Konstruktorfunktionen angegeben sind. Wenn jedoch später eine Eigenschaft zum <code>Employee</code> oder <code>WorkerBee</code> Prototyp hinzugefügt wird, wird diese Eigenschaft nicht von <code>Engineer</code> Objekt geerbt. Nimmt man zum Beispiel folgende Statements an:</p>

<pre class="brush: js notranslate">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>Das <code>jane</code> Objekt erbt nicht die <code>specialty</code> Eigenschaft. Man muss explizit den Prototypen einstellen, um dynamische Vererbung sicherzustellen. Nimmt man stattdessen folgende Statements an:</p>

<pre class="brush: js notranslate">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>Jetzt ist der Wert der <code>specialty</code> Eigenschaft des <code>jane</code> Objektes <code>"none"</code>.</p>

<p>Ein anderer Weg wür Vererbung ist der Einsatz der <code><a href="/de/docs/Web/JavaScript/Reference/Global_Objects/Function/call" title="en-US/docs/JavaScript/Reference/Global Objects/Function/call">call()</a></code> / <a href="/de/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" title="en-US/docs/JavaScript/Reference/Global Objects/Function/apply"><code>apply()</code></a> Methoden. Die folgenden Beispiele sind äquivalent:</p>

<div class="twocolumns">
<pre class="brush: js notranslate">function Engineer(name, projs, mach) {
  this.base = WorkerBee;
  this.base(name, 'engineering', projs);
  this.machine = mach || '';
}
</pre>

<pre class="brush: js notranslate">function Engineer(name, projs, mach) {
  WorkerBee.call(this, name, 'engineering', projs);
  this.machine = mach || '';
}
</pre>
</div>

<p>Der Einsatz von javascript <code>call()</code> Methode ergibt ein sauberere Implementierung, weil <code>base</code> nicht mehr benötigt wird.</p>

<h2 id="Eigenschaftsvererbung_erneut_besuchen">Eigenschaftsvererbung erneut besuchen</h2>

<p>Im vorangegangenen Abschnitten wurde beschrieben, wie JavaScript Konstruktoren und Prototypen Hierarchien und Vererbung bereitstellt. Dieser Abschnitt diskutiert einige Feinheiten, die in der vorherigen Diskussion nicht unbedingt ersichtlich waren.</p>

<h3 id="Lokale_versus_vererbte_Werte">Lokale versus vererbte Werte</h3>

<p>Wenn man auf eine Objekteigenschaft zugreift, führt JavaScript diese Schritte, wie vorhin in dem Kapitel beschrieben, durch:</p>

<ol>
 <li>Prüft, ob der Wert lokal existiert. Ist das der Fall, wird er zurückgegeben.</li>
 <li>Wenn kein lokaler Wert vorhanden ist, wird die Prototypenkette (über die <code>__proto__</code> Eigenschaft) geprüft.</li>
 <li>Wenn ein Objekt in der Prototypenkette einen Wert für die spezifizierte Eigenschaft hat, wird dieser zurückgegeben.</li>
 <li>Wenn keine solche Eigenschaft gefunden wird, hat das Objekt diese Eigenschaft nicht.</li>
</ol>

<p>Das Resultat dieser Schritte hängt davon ab, wie Dinge im Code definiert sind. Das originale Beispiel hat diese Definition:</p>

<pre class="brush: js notranslate">function Employee() {
  this.name = '';
  this.dept = 'general';
}

function WorkerBee() {
  this.projects = [];
}
WorkerBee.prototype = new Employee;
</pre>

<p>Nimmt man mit diesen Definitionen an, man erstellt <code>amy</code> als eine Instanz von <code>WorkerBee</code> mit folgendem Statement:</p>

<pre class="brush: js notranslate">var amy = new WorkerBee;
</pre>

<p>Das <code>amy</code> Objekt hat eine lokale Eigenschaft, <code>projects</code>. Die Werte der <code>name</code> und <code>dept</code> Eigenschaften sind nicht lokal in <code>amy</code> und werden über die Objekteigenschaft <code>__proto__</code> von <code>amy</code> erreicht. Deshalb hat <code>amy</code> diese Eigenschaftswerte:</p>

<pre class="brush: js notranslate">amy.name == '';
amy.dept == 'general';
amy.projects == [];
</pre>

<p>Nimmt man jetzt an, man ändert den Wert der <code>name</code> Eigenschaft in dem <code>Employee</code> Prototyp:</p>

<pre class="brush: js notranslate">Employee.prototype.name = 'Unknown';
</pre>

<p>Auf den ersten Blick erwartet man, dass der neue Wert an alle Instanzen von <code>Employee</code> propagiert wird. Jedoch ist das falsch.</p>

<p>Wenn man irgendeine Instanz des <code>Employee</code> Objektes erstellt, bekommt die Instanz einen <strong>lokalen Wert</strong> für die <code>name</code> Eigenschaft (der leere String). Das bedeutet, wenn man den <code>WorkerBee</code> Prototyp mit einem neuen <code>Employee</code> Objekt einstellt, dass <code>WorkerBee.prototype</code> einen lokalen Wert für die <code>name</code> Eigenschaft hat. Wenn demnach JavaScript nach der <code>name</code> Eigenschaft im <code>amy</code> Objekt sucht (eine Instanz von <code>WorkerBee</code>), wird der lokale Wert der Eigenschaft <code>WorkerBee.prototype</code> gefunden. Demnach wird nicht tiefer in der Kette in <code>Employee.prototype</code> gesucht.</p>

<p>Wenn man den Wert einer Objekteigenschaft zur Laufzeit ändert möchte und den neuen Wert für alle Nachkommenschaften dieses Objektes haben möchte, kann man die Eigenschaft nicht in der Konstruktorfunktion des Objektes definieren. Stattdessen fügt man sie zu dem Konstruktor assoziierten Prototyp hinzu. Angenommen man ändert zum Beispiel deb vorherigen Code wie folgt:</p>

<pre class="brush: js notranslate">function Employee() {
  this.dept = 'general';    // Note that this.name (a local variable) does not appear here
}
Employee.prototype.name = '';    // A single copy

function WorkerBee() {
  this.projects = [];
}
WorkerBee.prototype = new Employee;

var amy = new WorkerBee;

Employee.prototype.name = 'Unknown';
</pre>

<p>In diesem Fall wird die <code>name</code> Eigenschaft von <code>amy</code> <code>"Unknown"</code>.</p>

<p>Das Beispiel zeigt, dass wenn man Standardwerte für Objekteigenschaften haben möchte und zudem dass diese zur Laufzeit geändert werden können, muss man die Eigenschaft im Konstruktorprototypen setzen und nicht in der Konstruktorfunktion.</p>

<h3 id="Instanzbeziehungen_prüfen">Instanzbeziehungen prüfen</h3>

<p>Das Nachgucken von Eigenschaften in JavaScript prüft erst die eigenen Eigenschaften und wenn die Eigenschaft dort nicht ist die Eigenschaften der speziellen Eigenschaft <code>__proto__</code>. Das setzt sich rekursiv fort; der Prozess wird "nachschlagen in der Prototypenkette" genannt.</p>

<p>Die spezielle Eigenschaft <code>__proto__</code> wird beim erstellen des Objektes gesetzt; sie wird auf den Wert der <code>prototype</code> Eigenschaft des Konstruktors gesetzt. Deshalb erstellt der Ausdruck <code>new Foo()</code> ein Objekt mit <code>__proto__ == <code class="moz-txt-verticalline">Foo.prototype</code></code>. Folglich ändert die Änderung der <code class="moz-txt-verticalline">Foo.prototype</code> Eigenschaft alle Nachschlage Prozesse für alle Objekte, die mit <code>new Foo()</code> erstellt wurden.</p>

<p>Alle Objekte haben eine <code>__proto__</code> Objekteigenschaft (außer <code>Object</code>); Alle Funktionen haben eine <code>prototype</code> Objekteigenschaft. So können Objekte über 'Prototypenvererbung' mit anderen Objekten verbunden werden. Man kann auf Vererbung testen, indem <code>__proto__</code> eines Objekts mit einer <code>prototype</code> Objekt einer Funktion verglichen wird. JavaScript hat dafür eine Kurzschreibweise: der <code>instanceof</code> Operator prüft ein Objekt gegen eine Funktion und gibt <code>true</code> zurück, wenn das Objekt von dem Funktionsprototyp erbt. Zum Beispiel:</p>

<pre class="brush: js notranslate">var f = new Foo();
var isTrue = (f instanceof Foo);</pre>

<p>Für ein detailierteres Beispiel nehmen wir an, dass wir die gleichen Definition wie in <a href="#Eigenschaften_vererben">Eigenschaften vererben</a> haben. Ein <code>Engineer</code> wird wie folgt erstellt:</p>

<pre class="brush: js notranslate">var chris = new Engineer('Pigman, Chris', ['jsd'], 'fiji');
</pre>

<p>Mit diesem Objekt, sind alle folgenden Statements <code>true</code>:</p>

<pre class="brush: js notranslate">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>Damit kann man eine <code>instanceOf</code> Funktion wie folgt schreiben:</p>

<pre class="brush: js notranslate">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"><strong>Hinweis:</strong> Die obige Implementierung überprüft den Typ des Objekts gegen "xml", um eine Eigenart der Darstellung von XML-Objekten in neueren JavaScript-Versionen zu umgehen. die wesentlichen Details sind in {{bug(634150)}}, beschrieben.</div>

<p>Der Einsatz der oben definierten <code>instanceOf</code> Funktion führt bei folgenden Ausdrücken zu <code>true</code>:</p>

<pre class="brush: js notranslate">instanceOf(chris, Engineer)
instanceOf(chris, WorkerBee)
instanceOf(chris, Employee)
instanceOf(chris, Object)
</pre>

<p>Jedoch ist der folgende Ausdruck <code>false</code>:</p>

<pre class="brush: js notranslate">instanceOf(chris, SalesPerson)
</pre>

<h3 id="Globale_Informationen_in_Konstruktoren">Globale Informationen in Konstruktoren</h3>

<p>Wenn man einen Konstruktor erstellt, muss man vorsichtig sein, wenn man globale Informationen im Konstruktor einstellt. Nimmt man zum Beispiel an, man möchte eine eindeutige ID, die automatisch für jeden neuen <code>employee</code> zugewiesen wird, kann man die folgende Definition für <code>Employee</code> benutzen:</p>

<pre class="brush: js notranslate">var idCounter = 1;

function Employee(name, dept) {
   this.name = name || '';
   this.dept = dept || 'general';
   this.id = idCounter++;
}
</pre>

<p>Wenn man mit dieser Definition ein neuen <code>Employee</code> erstellt, weist der Konstruktor die nächste ID in der Sequenz zu und inkrementiert dann den globalen ID-Zähler. Wenn die nächsten Statemants die folgenden sind, so ist <code>victoria.id == 1</code> und <code>harry.id == 2</code>:</p>

<pre class="brush: js notranslate">var victoria = new Employee('Pigbert, Victoria', 'pubs');
var harry = new Employee('Tschopik, Harry', 'sales');
</pre>

<p>Auf den ersten Blick ist das super. Jedoch wird <code>idCounter</code> jedes mal, wenn ein <code>Employee</code> erstellt wird, wofür auch immer, inkrementiert. Wenn man eine <code>Employee</code> Hierarchie wie im Kapitel oben gezeigt, so wird der <code>Employee</code> Konstruktor für jedes einstellen des Prototypen aufgerufen. Angenommen man hat den folgenden Code:</p>

<pre class="brush: js notranslate">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>Angenommen die Definitionen lassen hier die <code>base</code> Eigenschaft weg und rufen den Konstruktor oberhalb in der Prototypenkette auf. In diesem Fall, bekommt das <code>mac</code> Objekt die id 5.</p>

<p>Abhängig von der Anwendung ist es sinnvoll oder auch nicht, dass der Zähler an diesen Stellen extra hochzählt. Wenn man an dem exakten Wert des Zählers interessiert ist, ist eine mögliche Lösung den folgenden Konstruktor zu nutzen:</p>

<pre class="brush: js notranslate">function Employee(name, dept) {
   this.name = name || '';
   this.dept = dept || 'general';
   if (name)
      this.id = idCounter++;
}
</pre>

<p>Wenn eine Instanz von <code>Employee</code> erstellt wird, der als Prototyp genutzt wird, übergibt man keine Argumente an den Konstruktor. Benutzt man diese Definition des Konstruktors, wird keine id vergeben und der Zäher nicht aktualisiert, wenn dem Konstruktor keine Argumente übergeben werden. Daraus folgt, dass man einem <code>Employee</code> einen Namen geben muss, damit er eine id erhält. In diesem Beispiel ist <code>mac.id == 1</code>.</p>

<p>Alternativ kann man <code>WorkerBee</code> eine Kopie des <code>Employee</code> Prototypenobjektes zuweisen:</p>

<pre class="brush: js notranslate">WorkerBee.prototype = Object.create(Employee.prototype);
// instead of WorkerBee.prototype = new Employee
</pre>

<h3 id="Keine_Mehrfachvererbung">Keine Mehrfachvererbung</h3>

<p>Einige objektorientierte SPrachen erlauben Mehrfachvererbung. Das bedeutet, dass ein Objekt die Eigenschaften und Werte von mehreren Elternobjekte erben kann. JavaScript unterstützt keine Mehrfachvererbung.</p>

<p>Vererbung von Eigenschafteswerten funktioniert zu JavaScripts Laufzeit durch das Suchen in der Prototypenkette eines Objektes. Weil ein Objekt ein einzigen Prototypen hat, kann JavaScript nicht dynamisch von mehr als einer Prototypenkette erben.</p>

<p>In JavaScript kann eine Konstruktorfunkton mehrere andere Konstruktorfunktionen in sich aufrufen. Das gibt die Illusion von Mehrfachvererbung. Zum Beispiel die folgenden Statements:</p>

<pre class="brush: js notranslate">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>Vorausgesetzt wird, die Definition von <code>WorkerBee</code> früher in diesem Kapitel. In diesem Fall hat das <code>dennis</code> Objekt die folgenden Eigenschaften:</p>

<pre class="brush: js notranslate">dennis.name == 'Doe, Dennis';
dennis.dept == 'engineering';
dennis.projects == ['collabra'];
dennis.machine == 'hugo';
dennis.hobby == 'scuba';
</pre>

<p><code>dennis</code> hat also die <code>hobby</code> Eigenschaften des <code>Hobbyist</code> Konstruktors bekommen. Setzt man jetzt noch voraus, dass danach Eigenschaften zum Konstruktorprototypen <code>Hobbyist</code> hinzugefügt werde:</p>

<pre class="brush: js notranslate">Hobbyist.prototype.equipment = ['mask', 'fins', 'regulator', 'bcd'];
</pre>

<p>Das <code>dennis</code> Objekt erbt diese neue Eigenschaft nicht.</p>

<div>{{PreviousNext("Web/JavaScript/Guide/Mit_Objekten_arbeiten", "Web/JavaScript/Guide/Using_promises")}}</div>