Was ist der Unterschied zwischen Anruf und Bewerbung?

3104

Was ist der Unterschied zwischen dem Verwenden callund applyAufrufen einer Funktion?

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

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

Gibt es Leistungsunterschiede zwischen den beiden oben genannten Methoden? Wann ist es am besten, callüber applyund umgekehrt zu verwenden?

John Duff
quelle
727
Denken Sie an ain gelten für Array von Argumenten und cin Aufruf für Spalten von Argumenten.
Larry Battle
176
@ LarryBattle Ich mache fast das gleiche, aber ich denke, ein in gelten für Array und c in Aufruf für Komma (dh durch Kommas getrennte Argumente).
Samih
3
Ich stimme zu, dass es dumm ist. Was ärgerlich ist, ist, dass diese Frage während der Interviews irgendwie gestellt wird, weil ein einflussreicher Trottel die Frage zu seiner Liste wichtiger Fragen hinzugefügt hat.
Ringo
6
Sie bewerben sich einmal (ein Argument), Sie rufen mehrmals an (mehrere Argumente). Alternative: Es gibt [auch?] Viele Call of Duty-Spiele.
Gras Double
1
Wenn die Absicht besteht, eine variable Funktion mit einer Liste von Argumentwerten unabhängig von "diesem" Wert aufzurufen, verwenden Sie den ES6-Spread-Operator, z. B. fn(...input)wenn die Eingabe ein Array ist. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Gajus

Antworten:

3648

Der Unterschied besteht darin, dass applySie die Funktion mit argumentsals Array aufrufen können . callerfordert, dass die Parameter explizit aufgelistet werden. Eine nützliche mnemonischen ist " A für eine rray und C für c omma."

Informationen zum Anwenden und Aufrufen finden Sie in der MDN-Dokumentation .

Pseudo-Syntax:

theFunction.apply(valueForThis, arrayOfArgs)

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

Ab ES6 besteht auch die Möglichkeit, spreaddas Array zur Verwendung mit der callFunktion zu verwenden. Die Kompatibilitäten finden Sie 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

Nulllinie
quelle
25
Eine Sache, die hinzugefügt werden muss, ist, dass die Argumente ein numerisches Array ([]) sein müssen. Assoziative Arrays ({}) funktionieren nicht.
Kevin Schroeder
326
@ KevinSchroeder: Wird im Javascript-Sprachgebrauch []als Array und {}als Objekt bezeichnet .
Martijn
89
Ich habe oft vergessen, welches Array benötigt wird und welches erwartet, dass Sie die Argumente auflisten. Eine Technik, an die ich mich erinnerte, ist, wenn der erste Buchstabe der Methode mit a beginnt, dann braucht es ein Array, dh ein Pply-Array
Aziz Punjani
16
@SAM Mit Anruf anstelle eines normalen Funktionsaufruf nur dann sinnvoll , wenn Sie den Wert ändern müssen diese für den Funktionsaufruf. Ein Beispiel (das ein Funktionsargument-Objekt in ein Array konvertiert): Array.prototype.slice.call(arguments)oder [].slice.call(arguments). apply ist sinnvoll, wenn Sie die Argumente in einem Array haben, beispielsweise in einer Funktion, die eine andere Funktion mit (fast) denselben Parametern aufruft. Empfehlung Verwenden Sie einen normalen Funktionsaufruf, funcname(arg1)wenn dies das ist, was Sie benötigen, und speichern Sie den Anruf und bewerben Sie sich für besondere Anlässe, wenn Sie sie wirklich benötigen.
einige
4
@KunalSingh Beide callund applynimmt zwei Parameter. Das erste Argument der apply' and Funktion call` muss das Eigentümerobjekt sein, und der zweite Parameter besteht aus Array- bzw. durch Kommas getrennten Parametern. Wenn Sie bestehen nulloder undefinedals erstes Argument, dann werden sie im nicht strengen Modus durch ein globales Objekt ersetzt, dhwindow
AJ Qarshi
229

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

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

Die Methode apply () ist identisch mit call (), außer dass apply () ein Array als zweiten Parameter erfordert. 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"]);
notnoop
quelle
42
Der zweite Parameter von apply () und call () ist optional und nicht erforderlich.
wütend Kiwi
34
Der erste Parameter ist ebenfalls nicht erforderlich.
Ikrom
@Ikrom, der erste Parameter ist nicht erforderlich für, callaber eine Anforderung für apply
iamcastelli
160

Um den Teil zu beantworten, wann die einzelnen Funktionen verwendet werden sollen, verwenden applySie , wenn Sie die Anzahl der übergebenen Argumente nicht kennen oder wenn sie sich bereits in einem Array oder einem Array-ähnlichen Objekt befinden (wie das argumentsObjekt zum Weiterleiten Ihrer eigenen Argumente). Verwenden Sie es callanders, da die Argumente nicht in ein Array eingeschlossen werden müssen.

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 (wie Ihr Beispiel) vorbei, ziehe ich es, callda ich Aufruf der Funktion. applywürde bedeuten, dass Sie die Funktion auf die (nicht vorhandenen) Argumente anwenden .

Es sollte keine Leistungsunterschiede geben, außer wenn Sie applydie Argumente verwenden und in ein Array einschließen (z . B. f.apply(thisObject, [a, b, c])anstelle von f.call(thisObject, a, b, c)). Ich habe es nicht getestet, daher könnte es Unterschiede geben, aber es wäre sehr browserspezifisch. Es ist wahrscheinlich callschneller, wenn Sie die Argumente noch nicht in einem Array haben, und applyschneller, wenn Sie dies tun.

Matthew Crumley
quelle
111

Hier ist eine gute Mnemonik. Eine Anwendung verwendet A- Rrays und A immer ein oder zwei Argumente. Wenn Sie C alles , was Sie haben C ount die Anzahl der Argumente.

Joe
quelle
2
Nützliche Mnemonik genau dort!. Ich werde das 'ein oder zwei Argumente' ändern, um 'maximal zwei Argumente' zu sagen, da weder der erste noch der zweite Parameter von applyerforderlich ist. Ich bin mir jedoch nicht sicher, warum man aufruft applyoder callohne Parameter. Es sieht so aus, als würde jemand versuchen herauszufinden, warum hier stackoverflow.com/questions/15903782/…
dantheta
92

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

Apply verwendet eine Reihe von Argumenten, während Call null oder mehr einzelne Parameter akzeptiert! Ah hah!

.apply(this, [...])

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

kmatheny
quelle
Dies hängt davon ab, was die Funktion mit den Parametern / dem Array macht. Wenn das Array nicht verarbeitet werden muss, dauert es weniger?
Eric Hodonsky
12
Interessanterweise ist der Aufruf auch ohne das Array noch viel schneller. jsperf.com/applyvscallvsfn2
Josh Mc
@JoshMc Das wäre sehr browserspezifisch. In IE 11 wird die Bewerbung doppelt so schnell ausgeführt wie der Anruf.
Vincent McNabb
1
1. Das Erstellen eines neuen Arrays bedeutet, dass der Garbage Collector es irgendwann bereinigen muss. 2. Der Zugriff auf Elemente im Array mithilfe der Dereferenzierung ist weniger effizient als der direkte Zugriff auf eine Variable (einen Parameter). (Ich glaube, das ist es, was kmatheny mit "Parsen" meinte, was eigentlich etwas ganz anderes ist.) Aber keines meiner Argumente erklärt den jsperf. Dies muss mit der Implementierung der beiden Funktionen durch die Engine zusammenhängen, z. B. erstellen sie möglicherweise ohnehin ein leeres Array, wenn keines übergeben wurde.
Joeytwiddle
Vielen Dank für das Teilen des Tests und des Videos
Gary
76

Es folgt ein Auszug aus Closure: The Definitive Guide von Michael Bolin . Es mag etwas lang aussehen, aber es ist voller Einsichten. Aus "Anhang B. Häufig missverstandene JavaScript-Konzepte":


Worauf thisbezieht sich, wenn eine Funktion aufgerufen wird ?

Beim Aufrufen einer Funktion des Formulars foo.bar.baz()wird das Objekt foo.barals Empfänger bezeichnet. Wenn die Funktion aufgerufen wird, wird der Empfänger als Wert für Folgendes 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 es beim Aufruf einer Funktion keinen expliziten Empfänger gibt, wird das globale Objekt zum Empfänger. Wie unter "goog.global" auf Seite 47 erläutert, ist window das globale Objekt, wenn JavaScript in einem Webbrowser ausgeführt wird. Dies führt zu überraschendem 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.addValuesund fbeziehen sich auf dieselbe Funktion, verhalten sie sich beim Aufruf unterschiedlich, da der Wert des Empfängers bei jedem Anruf unterschiedlich ist. Aus diesem Grund ist es beim Aufrufen einer Funktion, auf die thisverwiesen wird, wichtig sicherzustellen, dass sie beim Aufrufen thisden richtigen Wert hat. Um klar zu sein, wenn thisim Funktionskörper nicht darauf verwiesen würde, wäre das Verhalten von f(20)und obj.addValues(20)dasselbe.

Da Funktionen in JavaScript erstklassige Objekte sind, können sie ihre eigenen Methoden haben. Alle Funktionen haben die Methoden call()und apply()die es ermöglichen , den Empfänger neu zu definieren (dh das Objekt , das thissich bezieht) , wenn die Funktion aufgerufen wird . 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 darin apply()besteht, dass call()die Funktionsparameter als einzelne Argumente apply()empfangen werden , während sie als einzelnes Array empfangen werden:

// 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 fund obj.addValuesbeziehen sich auf dieselbe Funktion:

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

Da jedoch weder call()noch apply()verwendet den Wert des eigenen Empfängers Ersatz für den Empfänger Argument , wenn es nicht spezifiziert, die folgende nicht funktionieren:

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

Der Wert von thiskann niemals sein nulloder undefinedwenn eine Funktion aufgerufen wird. Wenn nulloder undefinedals Empfänger an call()oder geliefert apply()wird, wird stattdessen das globale Objekt als Wert für den Empfänger verwendet. Daher hat der vorherige Code den gleichen unerwünschten Nebeneffekt beim Hinzufügen einer Eigenschaft mit dem Namen valuezum globalen Objekt.

Es kann hilfreich sein, sich eine Funktion so vorzustellen, dass sie die Variable, der sie zugewiesen ist, nicht kennt. Dies hilft dabei, die Idee zu bekräftigen, dass der Wert davon gebunden wird, wenn die Funktion aufgerufen wird, anstatt wenn sie definiert wird.


Ende des Extrakts.

Dominykas Mostauskis
quelle
Nur um die Tatsache zu beachten, dass additionalValuesnicht innerhalb des obj.addValuesKörpers verwiesen wird
Viktor Stolbin
Ich weiß, dass Sie die Frage beantwortet haben, möchte aber hinzufügen: Sie hätten bind verwenden können, wenn Sie f definiert haben. var f = obj.addValues;wird var f = obj.addValues.bind(obj) und jetzt würde f (20) funktionieren, ohne jedes Mal einen Anruf verwenden oder anwenden zu müssen.
Jhliberty
Ich weiß, dass Sie es nicht geschrieben haben, aber Sie haben den Text und die Beispiele aus dem Buch als relevant hervorgehoben, und ich bin sehr dankbar. Sie waren sehr hilfreich.
Fralcon
34

Manchmal ist es nützlich, wenn ein Objekt die Funktion eines anderen Objekts ausleiht, was bedeutet, dass das ausleihende Objekt die verliehene Funktion einfach 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.

tjacks3
quelle
1
Für Leute, die wissen wollen, wie man sieht, console.logchecken Sie aus: Was ist console.log und wie verwende ich es?
Michel Ayres
25

Ein weiteres Beispiel mit Call, Apply und Bind. Der Unterschied zwischen Aufrufen und Übernehmen ist offensichtlich, aber Binden funktioniert folgendermaßen:

  1. Bind gibt eine Instanz einer Funktion zurück, die ausgeführt werden kann
  2. Erster Parameter ist ' dies '
  3. Der zweite Parameter ist eine durch Kommas getrennte Liste von Argumenten (wie Call ).

}}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/
Mahesh
quelle
23

Ich möchte ein Beispiel zeigen, in dem das Argument 'valueForThis' verwendet wird:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** Details: http://es5.github.io/#x15.4.4.7 *


quelle
20

Call () akzeptiert durch Kommas getrennte Argumente, z.

.call(scope, arg1, arg2, arg3)

und apply () verwendet eine Reihe von Argumenten, z.

.apply(scope, [arg1, arg2, arg3])

Hier einige weitere Anwendungsbeispiele: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

Mark Karwowski
quelle
`// call () === durch Kommas getrennte Argumente (Argumentliste) .call (this, args1, args2, args3, ...) // apply () === Array von Argumenten (Array-Elemente). bewerben (dies, [arr0, arr1, arr2, ...]) `
xgqfrms
19

Aus den MDN-Dokumenten auf Function.prototype.apply () :

Die Methode apply () ruft eine Funktion mit einer bestimmten Menge auf this Wert und Argumenten auf, die als Array (oder als Array-ähnliches Objekt) bereitgestellt werden.

Syntax

fun.apply(thisArg, [argsArray])

Aus den MDN-Dokumenten auf Function.prototype.call () :

Die Methode call () ruft eine Funktion mit einem bestimmten thisWert und Argumenten auf, die einzeln angegeben werden.

Syntax

fun.call(thisArg[, arg1[, arg2[, ...]]])

Aus Function.apply und Function.call in JavaScript :

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


Codebeispiel:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

Siehe auch diese Geige .

John Slegers
quelle
10

Hier ist ein kleiner Beitrag, den ich dazu geschrieben habe:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"
Dan
quelle
Hier ist noch eine: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply, aber im Grunde ist es richtig: .call (scope, arg1, arg2, arg3)
Mark Karwowski
7

Der Unterschied besteht darin, dass call()die Funktionsargumente separat und apply()die Funktionsargumente in einem Array verwendet werden.

Sanjib Debnath
quelle
6

Wir können Aufruf- und Anwendungsmethoden wie folgt unterscheiden

CALL: Eine Funktion mit Argumenten wird einzeln bereitgestellt. Wenn Sie die zu übergebenden Argumente kennen oder kein zu übergebendes Argument vorhanden ist, können Sie call verwenden.

APPLY: Rufen Sie eine Funktion mit Argument als Array auf. Sie können apply verwenden, wenn Sie nicht wissen, wie viele Argumente an die Funktion übergeben werden.

Die Verwendung von apply over call bietet den Vorteil, dass wir die Anzahl der Argumente nicht ändern müssen, sondern nur ein übergebenes Array ändern können.

Es gibt keinen großen Unterschied in der Leistung. Wir können jedoch sagen, dass der Aufruf im Vergleich zum Anwenden etwas schneller ist, da ein Array in der Apply-Methode ausgewertet werden muss.

Praveen D.
quelle
5

Der Unterschied zwischen diesen Methoden besteht darin, wie Sie die Parameter übergeben möchten.

"A für Array und C für Komma" ist eine praktische Mnemonik.

venkat7668
quelle
11
Was bietet diese Antwort, die in anderen Antworten noch nicht gut enthalten ist?
Kyll
5

Call und Apply werden verwendet, um den thisWert zu erzwingen , wenn eine Funktion ausgeführt wird. Der einzige Unterschied besteht darin , dass callnimmt n+1Argumente , wobei 1 thisund 'n' arguments. applyakzeptiert nur zwei Argumente, eines ist thisdas andere Argumentarray.

Der Vorteil , den ich in sehen applyüber callist , dass wir einfach einen Funktionsaufruf an andere Funktion ohne viel Aufwand delegieren;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

Beobachten Sie, wie einfach wir hellodie sayHelloVerwendung delegiert haben apply, aber calldies ist sehr schwer zu erreichen.

Raghavendra
quelle
4

Obwohl callund applydas Gleiche erreichen, denke ich, dass es mindestens einen Ort gibt, an dem Sie nicht verwenden können, callsondern nur verwenden können apply. In diesem Fall möchten Sie die Vererbung unterstützen und den Konstruktor aufrufen.

Mit dieser Funktion können Sie Klassen erstellen, die auch das Erstellen von Klassen durch Erweitern anderer Klassen unterstützt.

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6
Dhana Krishnasamy
quelle
Ich glaube, der Anruf würde dort mit dem Spread-Operator funktionieren, wie in der ausgewählten Antwort beschrieben. Es sei denn, ich vermisse etwas.
Jhliberty
4

Zusammenfassung:

Beide call()und apply()sind Methoden, die sich auf befinden Function.prototype. Daher sind sie für jedes Funktionsobjekt über die Prototypenkette verfügbar. Beide call()und apply()können eine Funktion mit einem bestimmten Wert von ausführen this.

Der Hauptunterschied zwischen call()und apply()ist die Art und Weise, wie Sie Argumente eingeben müssen. In beiden call()und apply()Sie übergeben als erstes Argument das Objekt, als das Sie den Wert haben möchten this. Die anderen Argumente unterscheiden sich folgendermaßen:

  • Mit call() Sie die Argumente normal eingeben (ab dem zweiten Argument)
  • Mit müssen apply()Sie eine Reihe von Argumenten übergeben.

Beispiel:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

Warum sollte ich diese Funktionen verwenden müssen?

Der thisWert kann manchmal in Javascript schwierig sein. Der Wert von thisbestimmt, wann eine Funktion ausgeführt wird, nicht, wenn eine Funktion definiert ist. Wenn unsere Funktion von einer richtigen thisBindung abhängt, können wir dieses Verhalten verwenden call()und apply()durchsetzen. Zum Beispiel:

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged

Willem van der Veen
quelle
4

Der Hauptunterschied besteht darin, dass wir mit call den Gültigkeitsbereich ändern und Argumente wie gewohnt übergeben können. Mit apply können Sie ihn jedoch mit Argumenten als Array aufrufen (als Array übergeben). Aber in Bezug auf das, was sie in Ihrem Code tun sollen, sind sie ziemlich ähnlich.

Während die Syntax dieser Funktion fast identisch mit der von apply () ist, besteht der grundlegende Unterschied darin, dass call () eine Argumentliste akzeptiert, während apply () ein einzelnes Array von Argumenten akzeptiert.

Wie Sie sehen, gibt es keinen großen Unterschied, aber es gibt Fälle, in denen wir call () oder apply () bevorzugen. Sehen Sie sich beispielsweise den folgenden Code an, mit dem die kleinste und größte Zahl in einem Array aus MDN mithilfe der Apply-Methode ermittelt wird:

// 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)

Der Hauptunterschied besteht also nur in der Art und Weise, wie wir die Argumente übergeben:

Call:

function.call(thisArg, arg1, arg2, ...);

Anwenden:

function.apply(thisArg, [argsArray]);
Alireza
quelle
2

Lassen Sie mich dem ein kleines Detail hinzufügen.

Diese beiden Anrufe sind fast gleichwertig:

func.call(context, ...args); // pass an array as list with spread operator

func.apply(context, args);   // is same as using apply

Es gibt nur einen kleinen Unterschied:

  • Der spreadOperator ... ermöglicht die Übergabe von iterable args als aufzurufende Liste.
  • Das applyakzeptiert nur Array-ähnliche Argumente.

Diese Aufrufe ergänzen sich also. Wo wir ein iterables erwarten , callfunktioniert, wo wir ein Array-ähnliches erwarten , applyfunktioniert.

Und für Objekte, die sowohl iterierbar als auch arrayartig sind , wie ein echtes Array, könnten wir technisch jedes davon verwenden, aber die Anwendung wird wahrscheinlich schneller sein, da die meisten JavaScript-Engines es intern besser optimieren.

Pravin Divraniya
quelle