Function.prototype.apply()

Die apply() Methode ruft eine Funktion mit gegebenem this Wert und arguments als Array (oder einem Array ├Ąhnlichem Objekt).

Hinweis: Die Syntax dieser Funktion ist gr├Â├čtenteils identisch zu der Funktion call(). Der fundamentale Unterschied ist, dass call() eine Liste von Argumenten und apply() ein Array mit Argumenten ├╝bergeben bekommt.

Syntax

function.apply(thisArg, [argsArray])

Parameter

thisArg
Optional. Der Wert von this, der f├╝r den Aufruf der Funktion func genutzt wird. Zu beachten ist, dass this m├Âglicherweise nicht der Wert ist, den die Methode sieht: Wenn die Methode eine Funktion im non-strict mode ist, werden null und undefined mit dem globalen Objekt ersetzt und primitive Werte werden in ein H├╝llobjekt umgewandelt.
argsArray
Optional. Ein Array ├Ąhnliches Objekt, welches die Argumente spezifiziert, welche beim Aufruf von func benutzt werden, oder null oder 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 Browserkompatibilit├Ąt gepr├╝ft werden.

R├╝ckgabewert

Das Ergebnis der aufgerufenen Funktion mit dem spezifischen this Wert und Parametern.

Beschreibung

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

apply ist sehr ├Ąhnlich zu call(), mit der Ausnahme des Typen der ├╝bergebenen Argumente. Man kann ein Array von Argumenten statt einer Menge von benannten Parametern benutzen. Mit apply kann man ein Arrayliteral benutzen, wie zum Beispiel fun.apply(this, ['eat', 'bananas']) oder ein Array Objekt, wie zum Beispiel fun.apply(this, new Array('eat', 'bananas')).

F├╝r den argsArray Parameter kann auch arguments eingesetzt werden. arguments 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 apply Methode genutzt wird. Man kann arguments nutzen, um alle Argumente eines Aufrufers zu ├╝bergeben. Das aufgerufene Objekt ist dann verantwortlich f├╝r das Verarbeiten der Argument.

Seit ECMAScript in der 5. Ausgabe kann jedes Objekt ├╝bergeben werden, welches Array ├Ąhnlich ist, was in der Praxis bedeutet, dass es eine length Eigenschaft hat und Ganzzahlige Eigenschaften im Bereich von 0 bis length-1 besitzt. Zum Beispiel kann man NodeList oder benutzerdefinierte Objekte wie { 'length': 2, '0': 'eat', '1': 'bananas' } benutzen.

Viele Browser, auch Chrome 14 und Internet Explorer 9, unterst├╝tzen keine Array ├Ąhnlichen Objekte, was zu einem Fehler f├╝hrt.

Beispiele

Einsatz von apply um ein Array an ein anderes zu h├Ąngen

Man kann push benutzen, um ein Element an ein Array anzuf├╝gen. Weil push eine variable Anzahl von Argumenten enth├Ąlt, kann man auch mehrere Element mit einem Aufruf hinzuf├╝gen. ├ťbergibt man jedoch ein Array an die push 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? concat 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!

apply ist die Funktion der Wahl!

var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array);  // ["a", "b", 0, 1, 2]

Einsatz von apply und eingebauten Standardfunktionen

Der clevere Einsatz von apply 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 Math.max/Math.min benutzt, um das maximalen/minimalen Wert in einem Array zu finden.

// 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];
  }
}

Jedoch muss man bei einem solchen Einsatz von apply 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 Argumentlimit von 65536), weil es in JavaScript nicht spezifiziert ist (tats├Ąchlich sogar die Art eines ├╝berm├Ą├čig gro├čen Stack-Verhaltens). 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 5, 6, 2, 3 ├╝ber apply im oberen Beispiel ├╝bergeben werden, statt dem ganzen Array.

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:

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]);

apply f├╝r das Verketten von Konstruktoren verwenden

Man kann apply einsetzen, um Konstruktoren f├╝r ein Objekt zu verketten, ├Ąhnlich wie in Java. Im folgenden Beispiel wird eine globale Function Methode namens construct erstellt, welche es erm├Âglicht ein Array ├Ąhnliches Objekt mit einem Konstruktor anstatt eines Argumentliste zu benutzen.

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

Hinweis: Die oben eingesetzte Object.create() Methode ist relativ neu. Alternativ kann eine der folgenden Ans├Ątze verwendet werden:

Einsatz von Object.__proto__:

Function.prototype.construct = function (aArgs) {
  var oNew = {};
  oNew.__proto__ = this.prototype;
  this.apply(oNew, aArgs);
  return oNew;
};

Einsatz von Closures:

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() {
    fConstructor.apply(this, aArgs);
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};

Einsatz von Function Konstruktoren:

Function.prototype.construct = function (aArgs) {
  var fNewConstr = new Function("");
  fNewConstr.prototype = this.prototype;
  var oNew = new fNewConstr();
  this.apply(oNew, aArgs);
  return oNew;
};

Beispiel f├╝r den Einsatz:

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'

Hinweis: Diese nicht native Function.construct Methode funktioniert nicht mit einigen nativen Konstruktoren (mit Date zum Beispiel). In diesem Fall muss man die Function.prototype.bind Methode (hat man zum Beispiel ein Array ├Ąhnliches Objekt wie folgt, um mit dem Date Konstruktor [2012, 11, 4] einzusetzen; in diesem Fall muss folgendes geschrieben werden: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() ÔÇö Jedoch ist das nicht die beste Art und Weise Probleme zu L├Âsen, weshalb diese L├Âsung nicht Praxistauglich ist).

Spezifikationen

Browserkompatibilit├Ąt

BCD tables only load in the browser

Siehe auch