Ich habe versucht, mich mit Rückrufen zu beschäftigen, und aus Neugier habe ich den Quellcode für Vanilla js in todomvc durchgesehen und diese Funktion gefunden:

Store.prototype.findAll = function (callback) {
    callback = callback || function () {};
    callback.call(this, JSON.parse(localStorage[this._dbName]).todos);

};

Was bedeutet die folgende Aussage?

callback = callback || function () {};

Bedeutet das, dass Rückrufe einfach leere Funktionen sind?

Auch was ist der Unterschied zwischen callback.call(this) und callback(anything)?

Ich habe versucht, diese Zeile zu ändern

callback.call(this, JSON.parse(localStorage[this._dbName]).todos);

Zu

callback(JSON.parse(localStorage[this._dbName]).todos);

Aber das Ergebnis war das gleiche. Warum sollte man callback.call statt einfach callback machen?

2
thedeliciousmuffin 10 Aug. 2015 im 17:30

3 Antworten

Beste Antwort

Sind Rückrufe in JavaScript nur leere Funktionen?

Rückrufe sind nicht nur leere Funktionen. Dies sind Funktionen, die später (oft mit einigen Argumenten) aufgerufen werden können. Manchmal sind sie optional und mit einer Host-Funktion können Sie den Rückruf weiterleiten oder den Rückruf nicht weiterleiten. Wenn der Rückruf nicht übergeben wird, kann die Host-Funktion erkennen, dass er nicht als Argument übergeben wurde, und sein Verhalten entsprechend anpassen.

Was bedeutet die folgende Aussage?

Rückruf = Rückruf || function () {};

Bedeutet das, dass Rückrufe einfach leere Funktionen sind?

Dies ist ein gängiges Entwurfsmuster, um sicherzustellen, dass ein Argument an eine Funktion einen aussagekräftigen Wert hat, falls es nicht vom Aufrufer übergeben wurde, damit die Funktion intern fortfahren und normal ausgeführt werden kann, vorausgesetzt, dass das Argument vom Aufrufer übergeben wurde, selbst wenn der Aufrufer dies nicht getan hat Das Argument nicht weitergeben.

Der Code callback = callback || function () {}; entspricht diesem:

if (callback) {
    callback = callback;
} else {
    callback = function() {};
}

In Javascript weist der Operator || das Ergebnis als den ersten der beiden Operanden zu, der wahr ist (oder false, wenn keiner der beiden wahr ist). Wenn also callback einen Wert hat, dann ist es wird das Ergebnis des Operanden || und Sie erhalten callback = callback. Wenn callback nicht wahr ist, weist es callback einen Standardfunktionswert zu, der es dem Rest der Funktion ermöglicht, unter der Annahme zu arbeiten, dass callback einen legitimen Wert hat. Dies verhindert, dass der gesamte Rest des Funktionscodes vor der Verwendung prüfen muss, ob callback einen legitimen Wert hat.

Was ist der Unterschied zwischen callback.call(this) und callback(anything)?

Mit someFunction.call() können Sie den Wert von this erreichen, wenn die Funktion ausgeführt wird. callback.call(this) bewirkt also, dass der Rückruf beim Ausführen denselben Wert wie this hat wie die aktuelle Funktion. Wenn Sie gerade callback(...) ohne .call() ausgeführt haben, nimmt this den Standardwert an, der entweder das window -Objekt ist oder im strengen Modus ausgeführt wird undefined.

Wenn sich der jeweilige Rückruf nicht zufällig auf den Wert von this in seinem Code bezieht, gibt es keinen Unterschied im Ergebnis, wenn .call() verwendet oder nicht verwendet wird. In diesem Fall ist dies jedoch der Fall Eine zusätzliche Funktion für den Rückruf, mit der auf die aktuelle Instanz des verwendeten Store - Objekts zugegriffen werden kann, indem auf den Wert this im Rückruf zugegriffen wird.


Wenn Sie den Wert von this wie folgt festlegen, können Sie eine Methode des Objekts als direkten Rückruf verwenden, da dies dieselbe Aufrufkonvention ist, die eine Objektmethode hat.

Wenn Sie also ein Store Objekt wie dieses hatten:

var s = new Store();

Und es gab eine Methode für dieses Objekt namens setName(), die this verwendet, um auf eine eigene Objektinstanz zu verweisen. Sie können Folgendes tun:

s.findAll(s.setName);

Dies würde nur funktionieren, weil callback.call(this) den Instanzwert im Rückruf auf den Wert this gesetzt hat.

2
jfriend00 10 Aug. 2015 im 15:40

Das Muster:

function foo(bar) {
  bar = bar || someDefault;
  ...
}

Ist eine übliche (aber veraltete) Methode, um einen Funktionsparameter auf einen Standardwert zu setzen, wenn er vom Aufrufer nicht definiert wurde.

In diesem Fall nutzt die Funktion alle Funktionen als wahr und JS 'ungewöhnlichen ODER-Operator, um callback festzulegen. zu einer leeren (nop) Funktion, wenn sie nicht gesetzt wurde. Sie können dieses Verhalten im folgenden Beispiel sehen:

var barDefault = 'No value provided!';

function foo(bar) {
  bar = bar || barDefault;
  console.log(bar);
}

foo(); // No value provided, since no arguments passed
foo(3); // Argument passed, value provided
foo(0); // Tricky case: falsy argument passed, so function assumes no value was provided

Wie Sie dem Beispiel entnehmen können, kann dieses Muster Probleme verursachen, wenn ein falsches Argument übergeben wurde, da der OR-Operator auf die Standardeinstellung zurückgreift. Um dies zu lösen, verwenden Sie:

bar = typeof bar !== 'undefined' ? bar : barDefault;

Wird explizit nach undefinierten Argumenten suchen.

Mit ES6 und Standardparameterwerten kann dies idiomatischer ausgedrückt werden als:

function foo(bar = someDefault) {
  ...
}
0
Community 23 Mai 2017 im 12:30

Nein, Rückrufe sind nicht "nur leer". Hier erhält die Funktion einen Rückruf als Argument und stellt einfach sicher, dass es sich um eine Funktion handelt. Wenn kein Rückruf übergeben wurde, wird er auf eine leere Funktion gesetzt, aber zumindest kann eine -Funktion aufgerufen werden. Das Setzen von Argumenten auf einen Standardwert (hier: eine leere Funktion) vereinfacht den folgenden Code, der andernfalls eine Reihe von if..else Bedingungen benötigt, um etwas anderes zu tun, wenn der Rückruf keine Funktion wäre.

Den anderen Teil der Frage finden Sie unter Wie funktioniert das Schlüsselwort "this"?.

2
Community 23 Mai 2017 im 12:06