aboutsummaryrefslogtreecommitdiff
path: root/files/de/web/javascript/reference/global_objects/function/apply/index.html
blob: 784843e2761d94edb64824a9e8e7636b57bb7363 (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
---
title: Function.prototype.apply()
slug: Web/JavaScript/Reference/Global_Objects/Function/apply
tags:
  - Function
  - JavaScript
  - Method
translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply
---
<div>{{JSRef}}</div>

<p>Die <code><strong>apply()</strong></code> Methode ruft eine Funktion mit gegebenem <code>this</code> Wert und <code>arguments</code> als Array (oder einem <a href="/de/docs/Web/JavaScript/Guide/Indexed_collections#Mit_Array-ähnlichen_Objekten_arbeiten">Array ähnlichem Objekt</a>).</p>

<div class="note">
<p><strong>Hinweis:</strong> Die Syntax dieser Funktion ist größtenteils identisch zu der Funktion {{jsxref("Function.call", "call()")}}. Der fundamentale Unterschied ist, dass <code>call()</code> <strong>eine Liste von Argumenten</strong> und <code>apply()</code> <strong>ein Array mit Argumenten</strong> übergeben bekommt.</p>
</div>

<div>{{EmbedInteractiveExample("pages/js/function-apply.html")}}</div>



<h2 id="Syntax">Syntax</h2>

<pre class="syntaxbox"><var>function</var>.apply(<var>thisArg</var>, [<var>argsArray</var>])</pre>

<h3 id="Parameter">Parameter</h3>

<dl>
 <dt><code>thisArg</code></dt>
 <dd>Optional. Der Wert von <code>this</code>, der für den Aufruf der Funktion <em><code>func</code></em> genutzt wird. Zu beachten ist, dass <code>this</code> möglicherweise nicht der Wert ist, den die Methode sieht: Wenn die Methode eine Funktion im {{jsxref("Functions_and_function_scope/Strict_mode", "non-strict mode", "", 1)}} ist, werden {{jsxref("Global_Objects/null", "null")}} und {{jsxref("Global_Objects/undefined", "undefined")}} mit dem globalen Objekt ersetzt und primitive Werte werden in ein Hüllobjekt umgewandelt.</dd>
 <dt><code>argsArray</code></dt>
 <dd>Optional. Ein Array ähnliches Objekt, welches die Argumente spezifiziert, welche beim Aufruf von <em><code>func</code></em> benutzt werden, oder {{jsxref("null")}} oder {{jsxref("undefined")}}, wenn keine Argumente übergeben werden. Mit Einführung von ECMAScript 5 können diese Argumente mit einem generische Array ähnliches Objekt statt einem Array übergeben werden. Für mehr Informationen sollte die {{anch("Browserkompatibilität", "Browserkompatibilität")}} geprüft werden.</dd>
</dl>

<h3 id="Rückgabewert">Rückgabewert</h3>

<p>Das Ergebnis der aufgerufenen Funktion mit dem spezifischen <code><strong>this</strong></code> Wert und Parametern.</p>

<h2 id="Beschreibung">Beschreibung</h2>

<p>Man kann ein anderes <code>this</code> Objekt für den Aufruf einer existierenden Funktion zuweisen. <code>this</code> referenziert zum aktuellen Objekte, dem aufrufenden Objekt. Mit <code>apply</code> kann eine Methode geschrieben und in einem anderen Objekt vererbt werden, ohne die Methode für das neue Objekte neu zu schreiben.</p>

<p><code>apply</code> ist sehr ähnlich zu {{jsxref("Function.call", "call()")}}, mit der Ausnahme des Typen der übergebenen Argumente. Man kann ein Array von Argumenten statt einer Menge von benannten Parametern benutzen. Mit <code>apply</code> kann man ein Arrayliteral benutzen, wie zum Beispiel <code>fun.apply(this, ['eat', 'bananas'])</code> oder ein {{jsxref("Array")}} Objekt, wie zum Beispiel <code>fun.apply(this, new Array('eat', 'bananas'))</code>.</p>

<p>Für den <code>argsArray</code> Parameter kann auch {{jsxref("Functions/arguments", "arguments")}} eingesetzt werden. <code>arguments</code> ist eine lokale Variable einer Funktion. Sie kann für alle nicht spezifizieren Argumente bei einem Aufruf benutzt werde. Dadurch muss man die Argumente eines Aufrufers nicht kennen, wenn die <code>apply</code> Methode genutzt wird. Man kann <code>arguments</code> nutzen, um alle Argumente eines Aufrufers zu übergeben. Das aufgerufene Objekt ist dann verantwortlich für das Verarbeiten der Argument.</p>

<p>Seit ECMAScript in der 5. Ausgabe kann jedes Objekt übergeben werden, welches Array ähnlich ist, was in der Praxis bedeutet, dass es eine <code>length</code> Eigenschaft hat und Ganzzahlige Eigenschaften im Bereich von <code>0</code> bis <code>length-1</code> besitzt. Zum Beispiel kann man {{domxref("NodeList")}} oder benutzerdefinierte Objekte wie <code>{ 'length': 2, '0': 'eat', '1': 'bananas' }</code> benutzen.</p>

<div class="note">Viele Browser, auch Chrome 14 und Internet Explorer 9, unterstützen keine Array ähnlichen Objekte, was zu einem Fehler führt.</div>

<h2 id="Beispiele">Beispiele</h2>

<h3 id="Einsatz_von_apply_um_ein_Array_an_ein_anderes_zu_hängen">Einsatz von <code>apply</code> um ein Array an ein anderes zu hängen</h3>

<p>Man kann <code>push</code> benutzen, um ein Element an ein Array anzufügen. Weil <code>push</code> eine variable Anzahl von Argumenten enthält, kann man auch mehrere Element mit einem Aufruf hinzufügen. Übergibt man jedoch ein Array an die <code>push</code> Methode, so wird das Array als ein Element hinzugefügt anstatt jedes Element des Arrays hinzuzufügen, was zu einem Array im Array führt. Was tun, wenn das nicht das ist, was gewollt ist? <code>concat</code> hat das gewünschte verhalten, jedoch erstellt es ein neues Array und fügt die Elemente nicht an das existierende Array. Was wenn man die Elemente unbedingt an das existierende Array hängen möchte? Eine Schleife schreiben? Sicher nicht!</p>

<p><code>apply</code> ist die Funktion der Wahl!</p>

<pre class="brush: js">var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array);  // ["a", "b", 0, 1, 2]
</pre>

<h3 id="Einsatz_von_apply_und_eingebauten_Standardfunktionen">Einsatz von <code>apply</code> und eingebauten Standardfunktionen</h3>

<p>Der clevere Einsatz von <code>apply</code> erlaubt es standard Functionen für Aufgaben zu benutzen, für die man sonst schleifen Schreiben müsste, um über alle Elemente eines Arrays zu iterieren. Im folgenden Beispiel wurde <code>Math.max</code>/<code>Math.min</code> benutzt, um das maximalen/minimalen Wert in einem Array zu finden.</p>

<pre class="brush: js">// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers);

// vs. simple loop based algorithm
max = -Infinity, min = +Infinity;

for (var i = 0; i &lt; numbers.length; i++) {
  if (numbers[i] &gt; max) {
    max = numbers[i];
  }
  if (numbers[i] &lt; min) {
    min = numbers[i];
  }
}
</pre>

<p>Jedoch muss man bei einem solchen Einsatz von <code>apply</code> vorsichtig sein, weil das Risiko da ist, dass man in das Limit der maximalen Argumente der JavaScriptumgebung überschreitet. Die Konsequenz aus dem ausführen von Funktionen mit zu vielen Argumenten (mehr als Zehntausend Argumente) ist, dass dieses Limit stark variiert (JavaScriptCore hat ein hart Codiertes <a class="link-https" href="https://bugs.webkit.org/show_bug.cgi?id=80797">Argumentlimit von 65536</a>), weil es in JavaScript nicht spezifiziert ist (<span id="result_box" lang="de"><span>tatsächlich sogar die Art eines übermäßig großen Stack-Verhaltens</span></span>). Einige Umgebungen erzeugen einen Fehler. Andere übergeben nicht alle Argumente der Funktion, um das Limit nicht zu überschreiten. Um diesen Fall man zu schildern: Wenn eine Umgebung ein Limit von 4 Argumenten hätte (aktuelle Limits sind natürlich signifikant höher), würde es so sein, als ob nur die Argumente <code>5, 6, 2, 3</code> über <code>apply</code> im oberen Beispiel übergeben werden, statt dem ganzen Array.</p>

<p>Wenn das Array in einigen Fällen so groß wird, dass es zehntausend Element erreicht, sollte eine hybride Strategie genutzt werden: Man teilt das Array auf und übergibt diese Teile der Funktion:</p>

<pre class="brush: js">function minOfArray(arr) {
  var min = Infinity;
  var QUANTUM = 32768;

  for (var i = 0, len = arr.length; i &lt; len; i += QUANTUM) {
    var submin = Math.min.apply(null,
                                arr.slice(i, Math.min(i+QUANTUM, len)));
    min = Math.min(submin, min);
  }

  return min;
}

var min = minOfArray([5, 6, 2, 3, 7]);
</pre>

<h3 id="apply_für_das_Verketten_von_Konstruktoren_verwenden"><code>apply</code> für das Verketten von Konstruktoren verwenden</h3>

<p>Man kann <code>apply</code> einsetzen, um {{jsxref("Operators/new", "Konstruktoren", "", 1)}} für ein Objekt zu verketten, ähnlich wie in Java. Im folgenden Beispiel wird eine globale {{jsxref("Function")}} Methode namens <code>construct</code> erstellt, welche es ermöglicht ein Array ähnliches Objekt mit einem Konstruktor anstatt eines Argumentliste zu benutzen.</p>

<pre class="brush: js">Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};
</pre>

<div class="note" style="height: 250px; overflow: auto;">
<p><strong>Hinweis:</strong> Die oben eingesetzte <code>Object.create()</code> Methode ist relativ neu. Alternativ kann eine der folgenden Ansätze verwendet werden:</p>

<p>Einsatz von {{jsxref("Object/__proto__", "Object.__proto__")}}:</p>

<pre class="brush: js">Function.prototype.construct = function (aArgs) {
  var oNew = {};
  oNew.__proto__ = this.prototype;
  this.apply(oNew, aArgs);
  return oNew;
};
</pre>

<p>Einsatz von <a href="/de/docs/Web/JavaScript/Closures">Closures</a>:</p>

<pre class="brush: js">Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() {
    fConstructor.apply(this, aArgs);
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};</pre>

<p>Einsatz von {{jsxref("Function")}} Konstruktoren:</p>

<pre class="brush: js">Function.prototype.construct = function (aArgs) {
  var fNewConstr = new Function("");
  fNewConstr.prototype = this.prototype;
  var oNew = new fNewConstr();
  this.apply(oNew, aArgs);
  return oNew;
};
</pre>
</div>

<p>Beispiel für den Einsatz:</p>

<pre class="brush: js">function MyConstructor() {
  for (var nProp = 0; nProp &lt; arguments.length; nProp++) {
    this['property' + nProp] = arguments[nProp];
  }
}

var myArray = [4, 'Hello world!', false];
var myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);                // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor);              // logs 'MyConstructor'
</pre>

<div class="note">
<p><strong>Hinweis:</strong> Diese nicht native <code>Function.construct</code> Methode funktioniert nicht mit einigen nativen Konstruktoren (mit {{jsxref("Date")}} zum Beispiel). In diesem Fall muss man die {{jsxref("Function.prototype.bind")}} Methode (hat man zum Beispiel ein Array ähnliches Objekt wie folgt, um mit dem {{jsxref("Global_Objects/Date", "Date")}} Konstruktor <code>[2012, 11, 4]</code> einzusetzen; in diesem Fall muss folgendes geschrieben werden: <code>new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()</code> — Jedoch ist das nicht die beste Art und Weise Probleme zu Lösen, weshalb diese Lösung nicht Praxistauglich ist).</p>
</div>

<h2 id="Spezifikationen">Spezifikationen</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Spezifikation</th>
   <th scope="col">Status</th>
   <th scope="col">Kommentar</th>
  </tr>
  <tr>
   <td>{{SpecName('ES3')}}</td>
   <td>{{Spec2('ES3')}}</td>
   <td>Initiale Definition. Implementiert in JavaScript 1.3.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.3.4.3', 'Function.prototype.apply')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td> </td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-function.prototype.apply', 'Function.prototype.apply')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td> </td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-function.prototype.apply', 'Function.prototype.apply')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td> </td>
  </tr>
 </tbody>
</table>

<h2 id="Browserkompatibilität">Browserkompatibilität</h2>

<div>


<p>{{Compat("javascript.builtins.Function.apply")}}</p>
</div>

<h2 id="Siehe_auch">Siehe auch</h2>

<ul>
 <li>{{jsxref("Functions/arguments", "arguments")}} object</li>
 <li>{{jsxref("Function.prototype.bind()")}}</li>
 <li>{{jsxref("Function.prototype.call()")}}</li>
 <li>{{jsxref("Functions", "Functions and function scope", "", 1)}}</li>
 <li>{{jsxref("Reflect.apply()")}}</li>
</ul>