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

<p>De <code><strong>apply()</strong></code> methode roept een functie aan met een gegeven <code>this</code> waarde en argumenten gedefineerd als een array (of een <a href="/en-US/docs/Web/JavaScript/Guide/Indexed_collections#Working_with_array-like_objects">array-achtig object</a>).</p>

<div class="note">
<p><strong>Let op:</strong> Hoewel de syntax van deze functie vrijwel gelijk is aan die van {{jsxref("Function.call", "call()")}}, is het fundamentele verschil met <code>call()</code> dat deze een <strong>lijst van argumenten</strong> accepteert, terwijl <code>apply()</code> een <strong>enkele array van argumenten</strong> verwacht.</p>
</div>

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

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

<h3 id="Parameters">Parameters</h3>

<dl>
 <dt><code>thisArg</code></dt>
 <dd>De waarde van this die aan de call voor <em>fun</em> wordt meegegeven. Hou er rekening mee dat dit mogelijk niet de waarde is die de methode ziet: Als de methode gedefineerd is in <a href="https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode" title="The documentation about this has not yet been written; please consider contributing!">non-strict mode</a> code, dan zullen <a href="https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/null" title="De waarde null representeerd voor het moedwillig weglaten, of de bedoelde afwezigheid van welk object of waarde dan ook. Het is een van JavaScript's primitive values."><code>null</code></a> en <a href="https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/undefined" title="The documentation about this has not yet been written; please consider contributing!"><code>undefined</code></a> worden vervangen met het globale object en primitieve waardes worden omgezet naar objecten (boxed).</dd>
 <dt><code>argsArray</code></dt>
 <dd>Een array-achtig object met de argumenten waarmee <em>fun </em>moet worden aangeroepen, of {{jsxref("null")}} of {{jsxref("undefined")}} als er geen argumenten worden gegeven. Vanaf ECMAScript 5  kunnen deze argumenten een generiek array-achtig object zijn in plaats van een array. Hieronder meer informatie over {{anch("Browser_compatibility", "browser compatibiliteit")}}.</dd>
</dl>

<h3 id="Return_waarde">Return waarde</h3>

<p>Het resultaat van de aanroep met de gegeven <code>this</code><strong> </strong>waarde en argumenten.</p>

<h2 id="Omschrijving">Omschrijving</h2>

<p>Het is mogelijk om een ander <code>this</code> object toe te wijzen indien je een bestaande functie aanroept. <code>this</code> verwijst naar het huidige object, het object dat de aanroep doet. Met <code>apply</code> kun je een methode eenmaal schrijven en het dan door overerving gebruiken in een ander object, zonder dat je de methode hoeft te herschrijven voor het nieuwe object.</p>

<p><code>Apply</code> heeft veel overeenkomsten met {{jsxref("Function.call", "call()")}} maar heeft voor argumenten een andere notatie. je kunt een array van argumenten meegeven in plaats van een benoemde set aan argumenten. Met apply kun je zowel een array literal (bijv. <code><em>fun</em>.apply(this, ['eat', 'bananas'])</code>) gebruiken als een {{jsxref("Array")}} object (bijv. <code><em>fun</em>.apply(this, new Array('eat', 'bananas'))</code>).</p>

<p>Je kunt ook {{jsxref("Functions/arguments", "arguments")}} meegeven als <code>argsArray</code> parameter. <code>arguments</code> is een locale variabele of functie, en kan gebruikt worden voor alle ongespecificeerde argumenten voor het aan te roepen object. Dit houdt in dat je niet precies hoeft te weten welke argumenten nodig zijn voor het aan te roepen object als je apply() gebruikt. Het aan te roepen object is vervolgens verantwoordelijk voor de afhandeling van de argumenten.</p>

<p>Vanaf de 5e editie van ECMAScript kun je ook een willekeurig array-achtig object gebruiken, wat inhoud dat het een <code>length</code> en getallen met bereik <code>(0 ... length-1)</code> als properties heeft. Je kunt bijvoorbeeld een {{domxref("NodeList")}} of een op maat gemaakt object (zoals: <code>{ 'length': 2, '0': 'eat', '1': 'bananas' }</code>) gebruiken.</p>

<div class="note">
<p><strong>Let op: </strong>De meeste browsers, waaronder Chrome 14 en Internet Explorer 9, ondersteunen array-achtige objecten nog niet. Deze zullen een exceptie geven als je het toch probeert.</p>
</div>

<h2 id="Voorbeelden">Voorbeelden</h2>

<h3 id="Apply_gebruiken_om_constructors_te_ketenen">Apply gebruiken om constructors te ketenen</h3>

<p>Apply kan gebruikt worden om {{jsxref("Operators/new", "constructors", "", 1)}} voor een object aan elkaar te ketenen, gelijk aan de werkwijze in java. In het volgende voorbeeld maken we een globale {{jsxref("Function")}} methode genaamd <code>construct</code>, welke je in staat stelt om een array-achtig object te gebruiken in plaats van een lijst van argumenten.</p>

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

<div class="note">
<p><strong>Let op:</strong> De <code>Object.create()</code> methode die hierboven gebruikt wordt is vrij nieuw. Voor een alternatieve methode die gebruik maakt van closures kun je onderstaande voorbeeld ook gebruiken:</p>

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

<p>Voorbeeld gebruik:</p>

<pre class="brush: js notranslate">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>Let op:</strong> Deze niet native Function.construct methode zal niet werken met sommige native constructors  (zoals {{jsxref("Date")}}, bij voorbeeld). In deze gevallen gebruik je de {{jsxref("Function.prototype.bind")}} methode (bij voorbeeld, stel je een array als de volgende voor, te gebruiken met {{jsxref("Global_Objects/Date", "Date")}} constructor: <code>[2012, 11, 4]</code>; in dit geval schrijf je bijvoorbeeld: <code>new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()</code> — Hoewel dit werkt is dit in meerdere opzichten een kwetsbare manier die niet in productie gebruikt zou moeten worden).</p>
</div>

<h3 id="Gebruik_van_apply_en_ingebouwde_functies">Gebruik van <code>apply</code> en ingebouwde functies</h3>

<p>Slim gebruik van apply geeft de mogelijkheid om standaard javascript functies te gebruiken voor handelingen die anders in een loop zouden gebeuren. Als voorbeeld gaan we <code>Math.max</code>/<code>Math.min</code> gebruiken wat de maximum en minimum waardes zijn in een array.</p>

<pre class="brush: js notranslate">// 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>Maar pas op: door apply op deze manier te gebruiken loop je het risico over de maximum argument limiet van JavaScript's engine heen te gaan. De consequenties van het gebruik van apply op een functie met te veel argumenten (denk aan meer dan tienduizen argumenten) varieren tussen de verschillende engines (JavaScriptCore heeft een hard-coded  <a class="link-https" href="https://bugs.webkit.org/show_bug.cgi?id=80797">argument limiet van 65536</a>), omdat de limiet (en het gedrag bij extreem grote hoeveelheden objecten) niet is opgenomen in een standaard. Sommige engines zullen een exceptie opgooien, anderen kunnen mogelijk zelfs het aantal argumenten afkappen bij het maximum. Als je array toch het risico loopt te groeien voorbij de limiet, kun je beter een hybriede implementatie maken: voer je functie uit over stukken van een array, bijvoorbeeld: </p>

<pre class="brush: js notranslate">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="Gebruik_van_apply_bij_monkey-patching">Gebruik van apply bij "monkey-patching"</h3>

<p>Apply kan enorm nuttig zijn bij het monkey-patchen van browser-eigen-  of framework-functies. Met bijvoorbeeld de <code>someobject.foo</code> functie, kun je de functie aanpassen op de volgende, ietwat smerige manier:</p>

<pre class="brush: js notranslate">var originalfoo = someobject.foo;
someobject.foo = function() {
  // Do stuff before calling function
  console.log(arguments);
  // Call the function as it would have been called normally:
  originalfoo.apply(this, arguments);
  // Run stuff after, here.
}
</pre>

<h2 id="Specificaties">Specificaties</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES3')}}</td>
   <td>{{Spec2('ES3')}}</td>
   <td>Initiele definitie. Geimplementeerd 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="Browser_compatibiliteit">Browser compatibiliteit</h2>

<div>{{CompatibilityTable}}</div>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
  </tr>
  <tr>
   <td>ES 5.1 generic array-like object as {{jsxref("Functions/arguments", "arguments")}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatGeckoDesktop("2.0")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Android</th>
   <th>Chrome for Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatVersionUnknown}}</td>
  </tr>
  <tr>
   <td>ES 5.1 generic array-like object as {{jsxref("Functions/arguments", "arguments")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoMobile("2.0")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<h2 id="Zie_ook">Zie ook</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>