Frage Was ist der Unterschied zwischen Anrufen und Anwenden?


Was ist der Unterschied zwischen der Verwendung? call und apply eine Funktion aufrufen?

var func = function() {
  alert('hello!');
};

func.apply(); vs func.call();

Gibt es Leistungsunterschiede zwischen den beiden oben genannten Methoden? Wann ist es am besten zu benutzen? call Über apply und umgekehrt?


2737
2017-12-31 19:56


Ursprung


Antworten:


Der Unterschied ist der apply können Sie die Funktion mit aufrufen arguments als ein Array; call erfordert, dass die Parameter explizit aufgelistet werden. Eine nützliche Gedächtnisstütze ist "EIN zum einRray und C zum cOmma. "

Siehe MDN-Dokumentation zu sich bewerben und Anruf.

Pseudosyntax:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

Es gibt auch ab ES6 die Möglichkeit spread das Array zur Verwendung mit dem call Funktion können Sie die Kompatibilitäten sehen Hier.

Beispielcode:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator


3304
2017-12-31 20:00



K. Scott Allen hat eine nette Beschreibung zu diesem Thema.

Sie unterscheiden sich grundsätzlich darin, wie sie mit Funktionsargumenten umgehen.

Die apply () -Methode ist identisch mit call (), außer dass apply () ein Array als zweiten Parameter benötigt. Das Array repräsentiert die Argumente für die Zielmethode. "

Damit:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

209
2017-12-31 19:59



Um den Teil zu beantworten, wann die einzelnen Funktionen verwendet werden sollen, verwenden Sie apply wenn Sie die Anzahl der Argumente nicht kennen, die Sie übergeben werden, oder wenn sie sich bereits in einem Array oder Array-ähnlichen Objekt (wie dem arguments Objekt, um eigene Argumente weiterzuleiten. Benutzen call Andernfalls müssen Sie die Argumente nicht in ein Array einschließen.

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

Wenn ich keine Argumente übergebe (wie dein Beispiel), bevorzuge ich call seit ich bin Berufung die Funktion. apply würde bedeuten, dass du es bist bewirbt sich die Funktion zu den (nicht vorhandenen) Argumenten.

Es sollte keine Leistungsunterschiede geben, außer vielleicht, wenn Sie verwenden apply und die Argumente in ein Array (z.B. f.apply(thisObject, [a, b, c]) Anstatt von f.call(thisObject, a, b, c)). Ich habe es nicht getestet, also könnte es Unterschiede geben, aber es wäre sehr Browser-spezifisch. Es ist wahrscheinlich, dass call ist schneller, wenn Sie die Argumente in einem Array nicht bereits haben und apply ist schneller, wenn Sie es tun.


150
2017-12-31 21:50



Hier ist eine gute Gedächtnisstütze. EINpply verwendet EINRitzen und EINEs dauert immer ein oder zwei Argumente. Wenn Sie verwenden Calles was du musst CZählen Sie die Anzahl der Argumente.


102
2017-09-04 13:36



Obwohl dies ein altes Thema ist, wollte ich nur darauf hinweisen, dass .call etwas schneller ist als .apply. Ich kann dir nicht genau sagen warum.

Siehe jsPerf, http://jsperf.com/test-call-vs-apply/3


[UPDATE!]

Douglas Crockford erwähnt kurz den Unterschied zwischen den beiden, was den Leistungsunterschied erklären kann ... http://youtu.be/ya4UHuXNygM?t=15m52s

Übernehmen verwendet ein Array von Argumenten, während Call keine oder mehrere einzelne Parameter benötigt! Ah hah!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)


91
2017-11-07 17:36



Folgt einem Auszug aus Abschluss: Der endgültige Leitfaden von Michael Bolin. Es könnte ein bisschen lang aussehen, aber es ist mit vielen Einsichten gesättigt. Aus "Anhang B. Häufig missverstandene JavaScript-Konzepte":


Was this Bezieht sich auf Wenn eine Funktion aufgerufen wird

Beim Aufruf einer Funktion des Formulars foo.bar.baz(), das Objekt foo.bar wird als der Empfänger bezeichnet. Wenn die Funktion aufgerufen wird, wird der Empfänger als Wert für verwendet this:

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
  for (var i = 0; i < arguments.length; i++) {
    this.value += arguments[i];
  }
  return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);

Wenn beim Aufruf einer Funktion kein expliziter Empfänger vorhanden ist, wird das globale Objekt zum Empfänger. Wie in "goog.global" auf Seite 47 erläutert, ist window das globale Objekt, wenn JavaScript in einem Webbrowser ausgeführt wird. Dies führt zu einem überraschenden Verhalten:

var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN

Obwohl obj.addValues und f beziehen sich auf die gleiche Funktion, verhalten sie sich anders, wenn sie gerufen werden, weil der Wert des Empfängers in jedem Anruf unterschiedlich ist. Aus diesem Grund beim Aufruf einer Funktion, auf die verwiesen wird thisEs ist wichtig, dies sicherzustellen this wird den richtigen Wert haben, wenn es aufgerufen wird. Um klar zu sein, wenn this wurden im Funktionskörper nicht referenziert, dann das Verhalten von f(20) und obj.addValues(20) wäre das gleiche.

Da Funktionen in JavaScript erstklassige Objekte sind, können sie ihre eigenen Methoden haben. Alle Funktionen haben die Methoden call() und apply() was es möglich macht, den Empfänger neu zu definieren (d. h. das Objekt, das this bezieht sich auf) beim Aufruf der Funktion. Die Methodensignaturen lauten wie folgt:

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

Beachten Sie, dass der einzige Unterschied zwischen call() und apply() ist das call() empfängt die Funktionsparameter als einzelne Argumente, während apply() empfängt sie als ein einzelnes Array:

// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);

Die folgenden Aufrufe sind äquivalent, wie f und obj.addValues beziehen sich auf die gleiche Funktion:

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

Jedoch seit keinem von beiden call() Noch apply() verwendet den Wert seines eigenen Empfängers, um das Empfängerargument zu ersetzen, wenn es nicht spezifiziert ist. Folgendes wird nicht funktionieren:

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

Der Wert von this kann nie sein null oder undefined wenn eine Funktion aufgerufen wird. Wann null oder undefined wird als Empfänger geliefert call() oder apply()Das globale Objekt wird stattdessen als Wert für den Empfänger verwendet. Daher hat der vorherige Code den gleichen unerwünschten Nebeneffekt des Hinzufügens einer benannten Eigenschaft value zum globalen Objekt.

Es kann hilfreich sein, an eine Funktion zu denken, die keine Kenntnis von der Variablen hat, der sie zugewiesen ist. Dies unterstützt die Idee, dass der Wert davon gebunden wird, wenn die Funktion aufgerufen wird und nicht wenn sie definiert ist.


Ende des Extrakts.


71
2017-12-04 12:41



Es ist manchmal nützlich, dass ein Objekt die Funktion eines anderen Objekts ausborgt, was bedeutet, dass das entleihende Objekt einfach die verliehene Funktion so ausführt, als wäre es seine eigene.

Ein kleines Codebeispiel:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

Diese Methoden sind sehr nützlich, um Objekten temporäre Funktionen zu geben.


33
2018-02-25 19:31