Deze vertaling is niet volledig. Help dit artikel te vertalen vanuit het Engels.
De apply()
methode roept een functie aan met een gegeven this
waarde en argumenten gedefineerd als een array (of een array-achtig object).
Let op: Hoewel de syntax van deze functie vrijwel gelijk is aan die van call()
, is het fundamentele verschil met call()
dat deze een lijst van argumenten accepteert, terwijl apply()
een enkele array van argumenten verwacht.
Syntax
fun.apply(thisArg, [argsArray])
Parameters
thisArg
- De waarde van this die aan de call voor fun wordt meegegeven. Hou er rekening mee dat dit mogelijk niet de waarde is die de methode ziet: Als de methode gedefineerd is in non-strict mode code, dan zullen
null
enundefined
worden vervangen met het globale object en primitieve waardes worden omgezet naar objecten (boxed). argsArray
- Een array-achtig object met de argumenten waarmee fun moet worden aangeroepen, of
null
ofundefined
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 browser compatibiliteit.
Return waarde
Het resultaat van de aanroep met de gegeven this
waarde en argumenten.
Omschrijving
Het is mogelijk om een ander this
object toe te wijzen indien je een bestaande functie aanroept. this
verwijst naar het huidige object, het object dat de aanroep doet. Met apply
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.
Apply
heeft veel overeenkomsten met 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. fun.apply(this, ['eat', 'bananas'])
) gebruiken als een Array
object (bijv. fun.apply(this, new Array('eat', 'bananas'))
).
Je kunt ook arguments
meegeven als argsArray
parameter. arguments
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.
Vanaf de 5e editie van ECMAScript kun je ook een willekeurig array-achtig object gebruiken, wat inhoud dat het een length
en getallen met bereik (0 ... length-1)
als properties heeft. Je kunt bijvoorbeeld een NodeList
of een op maat gemaakt object (zoals: { 'length': 2, '0': 'eat', '1': 'bananas' }
) gebruiken.
Let op: 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.
Voorbeelden
Apply gebruiken om constructors te ketenen
Apply kan gebruikt worden om constructors voor een object aan elkaar te ketenen, gelijk aan de werkwijze in java. In het volgende voorbeeld maken we een globale Function
methode genaamd construct
, welke je in staat stelt om een array-achtig object te gebruiken in plaats van een lijst van argumenten.
Function.prototype.construct = function (aArgs) { var oNew = Object.create(this.prototype); this.apply(oNew, aArgs); return oNew; };
Let op: De Object.create()
methode die hierboven gebruikt wordt is vrij nieuw. Voor een alternatieve methode die gebruik maakt van closures kun je onderstaande voorbeeld ook gebruiken:
Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr(); };
Voorbeeld gebruik:
function MyConstructor() { for (var nProp = 0; nProp < 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'
Let op: Deze niet native Function.construct methode zal niet werken met sommige native constructors (zoals Date
, bij voorbeeld). In deze gevallen gebruik je de Function.prototype.bind
methode (bij voorbeeld, stel je een array als de volgende voor, te gebruiken met Date
constructor: [2012, 11, 4]
; in dit geval schrijf je bijvoorbeeld: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()
— Hoewel dit werkt is dit in meerdere opzichten een kwetsbare manier die niet in productie gebruikt zou moeten worden).
Gebruik van apply
en ingebouwde functies
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 Math.max
/Math.min
gebruiken wat de maximum en minimum waardes zijn in een array.
// 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 < numbers.length; i++) { if (numbers[i] > max) { max = numbers[i]; } if (numbers[i] < min) { min = numbers[i]; } }
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 argument limiet van 65536), 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:
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < 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]);
Gebruik van apply bij "monkey-patching"
Apply kan enorm nuttig zijn bij het monkey-patchen van browser-eigen- of framework-functies. Met bijvoorbeeld de someobject.foo
functie, kun je de functie aanpassen op de volgende, ietwat smerige manier:
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. }
Specificaties
Specification | Status | Comment |
---|---|---|
ECMAScript 3rd Edition (ECMA-262) | Standard | Initiele definitie. Geimplementeerd in JavaScript 1.3. |
ECMAScript 5.1 (ECMA-262) The definition of 'Function.prototype.apply' in that specification. |
Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Function.prototype.apply' in that specification. |
Standard | |
ECMAScript Latest Draft (ECMA-262) The definition of 'Function.prototype.apply' in that specification. |
Draft |
Browser compatibiliteit
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
ES 5.1 generic array-like object as arguments |
(Yes) | 4.0 (2.0) | ? | ? | ? |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
ES 5.1 generic array-like object as arguments |
? | ? | 4.0 (2.0) | ? | ? | ? |