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
|
---
title: Closures (Funktionsabschlüsse)
slug: Web/JavaScript/Closures
tags:
- Closure
- ES5
- Intermediate
- JavaScript
- Reference
translation_of: Web/JavaScript/Closures
---
<div>{{jsSidebar("Intermediate")}}<br>
</div>
<p class="summary"><em>Closures</em> sind Funktionen mit unabhängigen, freien Variablen. Anders ausgedrückt: Die in der <em>Closure</em> definierte Funktion merkt sich die Umgebung, in der sie erzeugt wurde.</p>
<h2 id="Lexical_scoping">Lexical scoping</h2>
<h3 id="Lexikalischer_Geltungsbereich">Lexikalischer Geltungsbereich</h3>
<p>Betrachten wir folgendes Beispiel:</p>
<div>
<pre class="brush: js notranslate">function init() {
var name = "Mozilla"; // name ist eine von init erzeugte lokale Variable
function displayName() { // displayName() ist die innere, umschlossene Funktion, sprich die 'Closure'
alert(name); // hier wird die in der umschließenden Eltern-Funktion deklarierte Variable benutzt
}
displayName();
}
init();</pre>
</div>
<p><code>init()</code> erzeugt eine lokale Variable <code>name</code> und anschließend eine Funktion <code>displayName()</code>. <code>displayName()</code> ist eine interne Funktion definiert in <code>init()</code> und ist ausschließlich im Rahmen dieser Funktion verfügbar. <code>displayName()</code> besitzt keine eigenen lokalen Variablen, hat jedoch Zugriff auf Variablen umgebender Funktionen und kann darum die Variable <code>name</code> aus der umschließenden Eltern-Funktion abrufen.</p>
<p>{{JSFiddleEmbed("https://jsfiddle.net/78dg25ax/", "js,result", 250)}}</p>
<p>Dieses <a href="http://jsfiddle.net/xAFs9/3/" title="http://jsfiddle.net/xAFs9/">Code-Beispiel</a> zeigt, dass es funktioniert. Es handelt sich hier um einen lexikalischen Geltungsbereich (<em>lexical</em> <em>scoping</em>), d.h. in JavaScript wird der Geltungsbereich (<em>scope</em>) einer Variablen bestimmt durch ihren Fundort im Quellcode (darum lexikalisch). Und verschachtelte Funktionen haben Zugriff auf Variablen, die im umschließenden Geltungsbereich (<em>outer scope</em>) deklariert werden.</p>
<h2 id="Closure">Closure</h2>
<h3 id="Funktionsabschluss">Funktionsabschluss</h3>
<p>Betrachten wir folgendes Beispiel:</p>
<pre class="brush: js notranslate">function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
</pre>
<p>Zum Laufen gebracht zeigt dieser Code exakt den gleichen Effekt wie das vorherige <code>init()</code> Beispiel: Die Zeichenfolge "Mozilla" wird als JavaScript <em>alert</em> Meldung angezeigt. Der interessante Unterschied besteht darin, dass die innere Funktion <code>displayName()</code> von der äußeren Funktion schon vor ihrer Ausführung zurückgegeben wurde.</p>
<p>Dass der Code weiterhin funktioniert, mag verwundern. Üblicherweise existieren die in einer Funktion enthaltenen lokalen Variablen nur während ihrer Ausführung. Man könnte also annehmen, dass die Variable <code>name</code> nicht mehr abrufbar ist, nachdem <code>makeFunc()</code> geendet hat. Da der Code trotzdem funktioniert, ist dies offensichtlich nicht der Fall.</p>
<p>Des Rätsels Lösung ist, dass <code>myFunc</code> zu einem Funktionsabschluss, einer <em>Closure</em>, geworden ist. Die <em>Closure</em> ist ein besonderes Objekt mit zwei außergewöhnlichen Merkmalen – sie umfasst sowohl die Funktion, wie auch das Umfeld, in dem diese erzeugt wurde. Dieses Umfeld besteht aus sämtlichen lokalen Variablen, die im Geltungsbereich (<em>Scope</em>) lagen zum Zeitpunkt der Erzeugung der <em>Closure.</em> Im obigen Beispiel ist <code>myFunc</code> eine <em>Closure</em>, die sowohl die Funktion <em>myFunc</em>, wie auch die Zeichenfolge "Mozilla", die bei der Erzeugung der <em>Closure</em> exisitierte, umfasst. </p>
<p>Hier nun ein etwas interessanteres Beispiel, eine <code>makeAdder()</code> Funktion:</p>
<pre class="brush: js notranslate">function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
</pre>
<p>In diesem Beispiel haben wir eine Funktion <code>makeAdder(x)</code> definiert, die ein einzelnes Argument <code>x</code> erwartet und eine neue Funktion zurück gibt. Die zurückgegebene Funktion erwartet ein Argument <code>y</code> und liefert die Summe von <code>x</code> und <code>y</code> als Ergebnis.</p>
<p>Die Funktion <code>makeAdder</code> ist im Wesentlichen eine Factory für spezielle Funktionen: sie erzeugt Funktionen, welche ihrem Argument einen bestimmten Wert hinzuaddieren. Im vorangegangenen Beispiel erzeugen wir mittels dieser Factory zwei neue Funktionen: eine von ihnen addiert 5 zu ihrem Argument, die andere addiert 10 hinzu.</p>
<p><code>add5</code> und <code>add10</code> sind beides Closures. Sie teilen beide den selben Funktionsrumpf, behalten aber verschiedene Kontexte. In <code>add5</code>'s Kontext ist <code>x</code> 5, im Kontext von <code>add10</code> ist <code>x</code> 10.</p>
<h2 id="Practical_closures">Practical closures</h2>
<h3 id="Closures_in_der_Praxis">Closures in der Praxis</h3>
<p>Soviel zur Theorie von Closures — aber gibt es tatsächlich einen Praxisnutzen? Betrachten wir dafür die Auswirkungen in der Praxis. Ein Closure lässt uns Daten (die Ausführungsumgebung) mit einer Funktion, die auf diesen Daten operiert, verbinden. Das hat offensichtliche Parallelen zur objektorientierten Programmierung, bei der die Daten eines Objekts (die Objekteigenschaften) mit einer oder mehreren Methoden verbunden werden. Somit kann ein Closure immer dann verwendet werden, wo normalerweise ein Objekt mit einer einzigen Methode verwendet wird.</p>
<p>Besonders im Web kommt uns das häufig entgegen. Ein Großteil von JavaScript-Code ist ereignisbasierter Code: wir definieren erst ein Verhalten, und hängen es dann an ein Benutzerereignis (bspw. einen Mausklick oder Tastendruck). Unser Code nimmt dabei üblicherweise die Form eines Callback an: eine einzelne Funktion, die bei Eintreten des Ereignisses aufgerufen wird.</p>
<p>Hier ein Beispiel aus der Praxis: Angenommen, wir wollen Buttons auf einer Seite hinzufügen, die die Schriftgröße ändern – eine Möglichkeit wäre, die Schriftgröße mittels der Eigenschaft <code>font-size</code> im <code>body</code>-Element in Pixel (<code>px</code>) zu setzen und bei anderen Elementen der Seite (z.B. <em>header</em>-Elemente wie <code>h1</code>, <code>h2</code>) die Eigenschaft <code>font-size</code> in der relativen Einheit <code>em</code> anzugeben:</p>
<pre class="brush: css notranslate">body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
}
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.2em;
}
</pre>
<p>Unser interaktiver Schriftgößen-Button ändert die <code>font-size</code>-Eigenschaft des <code>body</code>-Elements. Diese Änderung wird von den anderen Elementen auf der Seite wahrgenommen und die Elemente passen sich dank der relativen Einheit <code>em</code> nun der neuen Schriftgröße an.</p>
<p>Hier das JavaScript:</p>
<pre class="brush: js notranslate">function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}
var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
</pre>
<p><code>size12</code>, <code>size14</code> und <code>size16</code> sind nun Funktionen, die den <code>body</code>-Text in Schriftgröße 12 Pixel, 14 Pixel oder 16 Pixel ändern. Diese Funktionen können nun wie folgt als Buttons (in diesem Fall als Links) hinzugefügt werden:</p>
<pre class="brush: js notranslate">document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
</pre>
<pre class="brush: html notranslate"><a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
</pre>
<p>{{JSFiddleEmbed("https://jsfiddle.net/vnkuZ/7726/","","200")}}</p>
<h2 id="Emulation_privater_Methoden_mit_Hilfe_von_Closures">Emulation privater Methoden mit Hilfe von Closures</h2>
<p>Sprachen wie Java bieten die Möglichkeit Methoden als privat zu deklarieren, was bedeutet, dass sie nur von anderen Methoden der gleichen Klasse aufgerufen werden können.</p>
<p>Dies ist in JavaScript nicht explizit vorgesehen, aber es kann mit Hilfe von Funtionsabschlüssen nachgebildet werden. Private Methoden sind nicht nur nützlich um den Zugriff auf Code einzuschränken: sie bieten auch ein mächtiges Werkzeug um den globalen Namensraum zu verwalten indem sie weniger wichtige Methoden vor dem öffentlichen Interface verbergen.</p>
<p>Das folgende Beispiel zeigt, wie man ein paar öffentliche Funktionen definiert, welche Zugriff auf private Funktionen und Variablen haben, indem man <em>Closures </em>verwendet. Die ist auch als <a class="external" href="http://www.google.com/search?q=javascript+module+pattern" title="http://www.google.com/search?q=javascript+module+pattern">module pattern</a> bekannt:</p>
<pre class="brush: js notranslate">var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
</pre>
<p>In den vorhergehenden Beispielen hatte jede <em>Closure </em>ihr eigenes Umfeld; hier erzeugen wir ein einziges Umfeld, welches von 3 Funktionen geteilt wird: <code>counter.increment</code>, <code>counter.decrement</code> und <code>counter.value</code>.</p>
<p>Das gemeinsame Umfeld wird im Inneren einer anonymen Funktion erzeugt, welche nach der Definition auch gleich aufgerufen wird. Das Umfeld enthält 2 private Dinge: eine Variable mit dem Namen <code>privateCounter</code> und eine Funktion mit dem Namen <code>changeBy</code>. Auf keines von diesen privaten Dingen kann von ausserhalb der anonymen Funktion zugegriffen werden. Statt dessen muß auf sie mit Hilfe der drei öffentlichen Funktionen zugegriffen werden, welche von der anonymen Funktion zurueckgegeben werden.</p>
<p>Diese drei öffentlichen Funktionen sind <em>Closures</em>, welche das gleiche Umfeld teilen. Wegen JavaScripts lexikalischem Geltungsbereich haben sie alle Zugriff auf die <code>privateCounter</code> Variable und die <code>changeBy</code> Funktion.</p>
<div class="note">
<p>Du siehst: wir definieren eine anonyme Funktion, die einen Zähler erzeugt, und dann rufen wir sie unmittelbar auf und weisen das Ergebnis der <code>counter</code> Variablen zu. Wir könnten diese Funktion in einer separaten Variablen <code>makeCounter</code> speichern und sie zum Erzeugen mehrerer Zähler benutzen.</p>
</div>
<pre class="brush: js notranslate">var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* Alerts 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* Alerts 2 */
counter1.decrement();
alert(counter1.value()); /* Alerts 1 */
alert(counter2.value()); /* Alerts 0 */
</pre>
<p>Beachte wie jeder der zwei Zähler, <code>counter1</code> und <code>counter2</code>, seine Unabhängigkeit vom anderen erhält. Jede <em>Closure </em>referenziert eine andere Version der <code>privateCounter</code> Variablen durch ihren eigene Closure. Jedes mal, wenn einer der Zähler aufgerufen wird, ändert sich das lexikalische Umfeld durch ändern des Wertes dieser Variablen; jedoch haben Änderungen des Wertes der Variablen in der einen <em>Closure</em> keinen Einfluss auf den Wert in der anderen <em>Closure</em>.</p>
<div class="note">
<p>Diese Art <em>Closures </em>zu verwenden bietet einige Vorteile, die man der Objekt orientierten Progammierung zuspricht, insbesondere Daten verbergen und Klammerung.</p>
</div>
<h2 id="Closure_Scope_Chain">Closure Scope Chain</h2>
<h3 id="Kette_von_Closure_Geltungsbereichen">Kette von Closure Geltungsbereichen</h3>
<p>Für jede <em>Closure </em>haben wir drei Geltungsbereiche:</p>
<ul>
<li>Lokaler Geltungsbereich (Eigener Geltungsbereich)</li>
<li>Geltungsbereich der Äusseren Funktionen</li>
<li>Globaler Geltungsbereich</li>
</ul>
<p>Wir haben also drei Geltungsbereiche für eine <em>Closure</em>. Aber häufig machen wir Fehler, wenn wir geschachtelte innere Funktionen haben. Betrachten wir das folgende Beispiel:</p>
<pre class="brush: js notranslate">// global scope
var e = 10;
function sum(a){
return function(b){
return function(c){
// outer functions scope
return function(d){
// local scope
return a + b + c + d + e;
}
}
}
}
console.log(sum(1)(2)(3)(4)); // log 20
// We can also write without anonymous functions:
// global scope
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// outer functions scope
return function sum4(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var s = sum(1);
var s1 = s(2);
var s2 = s1(3);
var s3 = s2(4);
console.log(s3) //log 20
</pre>
<p>Also in dem obigen Beispiel haben wir eine Serie von geschachtelten Funktionen, die alle Zugriff auf den Geltungsbereich der äusseren Funktionen haben aber fälschlicherweise oft angenommen wird, dass sie Zugriff nur auf den Geltungsbereich der nächsten äusseren Funktion haben. Zur Verdeutlichung kann man sagen, dass alle <em>Closures </em>Zugriff auf die Geltungsbereiche aller Funktionen haben, innerhalb derer sie deklariert sind.</p>
<h2 id="Creating_closures_in_loops_A_common_mistake">Creating closures in loops: A common mistake</h2>
<h3 id="Erzeugen_von_Closures_in_Schleifen_Ein_häufiger_Fehler">Erzeugen von <em>Closures </em>in Schleifen: Ein häufiger Fehler</h3>
<p>Vor der Einführung des <a href="/en-US/docs/Web/JavaScript/Reference/Statements/let" title="let"><code>let</code></a> Schlüsselwortes in ECMAScript 6, gab es ein häufiges Problem mit <em>Closures</em>, wenn sie innerhalb einer Schleife erzeugt wurden. Hier ein Beispiel:</p>
<pre class="brush: html notranslate"><p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>
</pre>
<pre class="brush: js notranslate">function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
}
setupHelp();
</pre>
<p>{{JSFiddleEmbed("https://jsfiddle.net/v7gjv/8164/", "", 200)}}</p>
<p>Das <code>helpText</code> Array definiert drei Hilfshinweise, die jeweils mit der ID eines Eingabefeldes verknüpft sind. Die Schleife geht durch diese Definitionen und hängt an das <code>onfocus</code> Ereignis die entsprechende Hilfemethode.</p>
<p>Wenn du aber diesen Code ausprobierst, wirst du sehen, dass er nicht tut was er sollte. Egal auf welches Feld du den Fokus gibst, es wird immer die Meldung über dein Alter gezeigt.</p>
<p>Der Grund dafür ist, dass die Callbacks, die an <code>onfocus</code> gehängt sind, <em>Closures </em>sind; sie bestehen aus der Funktionsdefinition und dem Umfeld aus dem Geltungsbereich von <code>setupHelp</code>. Drei <em>Closures</em> wurden von der Schleife erzeugt, aber jede benutzt das gleiche gemeinsame lexikalische Umfeld, das eine Variable mit sich änderndem Wert besitzt (<code>item.help</code>). Der Wert von <code>item.help</code> wird bestimmt, wenn die <code>onfocus</code> Callbacks ausgeführt werden. Weil aber die Schleife zu dieser Zeit bereits gelaufen ist, zeigt das <code>item</code> Objekt (das von allen drei <em>Closures </em>geteilt wird) weiterhin auf den letzten Eintrag in der <code>helpText</code> Liste.</p>
<p>Eine Lösung ist in diesem Fall die Benutzung von mehreren <em>Closures</em>: insbesondere, eine Funktionsfabrik zu benutzten wie früher beschrieben:</p>
<pre class="brush: js notranslate">function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function makeHelpCallback(help) {
return function() {
showHelp(help);
};
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
}
}
setupHelp();
</pre>
<p>{{JSFiddleEmbed("https://jsfiddle.net/v7gjv/9573/", "", 300)}}</p>
<p>Das tut wie erwartet. Anstatt den Callbacks ein gemeinsames lexikales Umfeld zu geben erzeugt die <code>makeHelpCallback</code> Funktion ein neues lexikalisches Umfeld für jeden Callback, in dem sich <code>help</code> auf den entsprechenden String aus dem <code>helpText</code> Array bezieht.</p>
<p>Ein anderer Weg das obige mit einer anonymonen <em>Closure</em> zu schreiben ist:</p>
<pre class="brush: js notranslate">function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
(function() {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
})(); // Immediate event listener attachment with the current value of item (preserved until iteration).
}
}
setupHelp();</pre>
<p>Wenn du nicht mehrere <em>Closures </em>benutzten möchtest, kannst du das <code><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let">let</a></code> Schlüsselwort benutzen, das in ES2015 eingeführt wurde:</p>
<pre class="brush: js notranslate">function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
let item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
}
setupHelp();</pre>
<p>Dieses Beispiel benutzt <code>let</code> anstatt <code>var</code>, so dass jede Closure die blocksichtbare Variable bindet, was bedeutet, dass keine zusätzlichen <em>Closures </em>gebraucht werden.</p>
<p>Eine weitere Alternative könnte sein <code>forEach()</code> für die Iteration über das <code>helpText</code> Array zu benutzen und einen Callback für jeden {{htmlelement("div")}} zuzuweisen, wie hier gezeigt:</p>
<pre class="brush: js notranslate">function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
helpText.forEach(function(text) {
document.getElementById(text.id).onfocus = function() {
showHelp(text.help);
}
});
}
setupHelp();</pre>
<h2 id="Performance_considerations">Performance considerations</h2>
<h3 id="Effizienzbetrachtungen">Effizienzbetrachtungen</h3>
<p>Es ist unklug unnötigerweise Funktionen innerhalb anderer Funktionen zu erzeugen, wenn <em>Closures </em>für eine bestimmte Aufgabe nicht gebraucht werden. Denn es hat negativen Einfluss auf die Scripteffizienz sowohl in Bezug auf Geschwindigkeit als auch Speicherbedarf.</p>
<p>Wenn zum Beispiel ein neues Objekt/Klasse erzeugt wird, sollten die Methoden mit dem Prototypen des Objekts verbunden sein anstatt im Objektkonstuktor erzeugt werden. Der Grund ist, dass immer wenn der Konstruktor aufgerufen wird, die Methoden neu zugewiesen würden (das heisst, für jede Objekterzeugung).</p>
<p>Betrachte folgenden Fall:</p>
<pre class="brush: js notranslate">function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
this.getName = function() {
return this.name;
};
this.getMessage = function() {
return this.message;
};
}
</pre>
<p>Da der vorliegende Code die Vorteile von <em>Closures </em>in diesem speziellen Fall nicht nutzt, könnten wir ihn umschreiben so dass wir die <em>Closure </em>vermeiden:</p>
<pre class="brush: js notranslate">function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
</pre>
<p>Es wird jedoch nicht empfohlen, den Prototyp neu zu definieren. Das folgende Beispiel erweitert statt dessen den existierenden Prototyp:</p>
<pre class="brush: js notranslate">function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};
</pre>
<p>In den zwei vorhergehenden Beispielen kann der vererbte Prototyp von allen Objekten benutzt werden und die Definition der Methoden muss nicht bei jeder Objekterzeugung durchgeführt werden. Weitere Informationen unter <a href="/de/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">Details zum Objektmodell</a>.</p>
|