Die Speicherung von Referenz-Funktion im Objekt/variable
Habe ich gesucht, um für diese aber bisher nicht in der Lage zu finden, ein Duplikat, ich kann mit den falschen keywords...
Ich versuche, ändern Sie vorübergehend eine Funktion in einem Objekt gespeichert, aber ich habe Probleme bei der Einstellung zurück zu dem, was es vorher war.
Bedenken Sie:
//Set the options object
var options = {
success: function(){
console.log('Original Function Called');
}
}
//Save the options
$('#foo').data('bar',options);
Und dann in einer anderen Funktion:
//Get the options
var options = $('#foo').data('bar');
//Store the old options
var old_options = options;
//Temporarily change the success function
options.success = function(){
console.log('Temporary Function Called');
}
//Save the options
//This allows the other functions to access the temporary function
$('#foo').data('bar',options);
//Do stuff here that uses the new options
//Reset the options to include the original success function
$('#foo').data('bar',old_options);
Hätte ich erwartet, dass das nur die Anzeige Temporary Function Called
einmal, es scheint jedoch, um vollständig ersetzen Sie die alte success
Rückruf mit der temporären Rückruf.
Kann mir jemand sagen warum und wie kann ich dies umgehen?
UPDATE
Dachte ich, dass extend
würde dieses Problem beheben, aber es scheint, dass das Problem vielleicht ein bisschen tiefer. Ich habe beschlossen, zu veröffentlichen ein snippet von meinem eigentlichen code dieser Zeit. Bitte beachten Sie die folgenden Punkte, bevor Sie Lesen:
SM
ist ziemlich viel nur ein alias vonjQuery
, bitte ignorieren Sie es.success
underror
werden Parameter geliefert, um die Funktion
Hier ist mein code:
//Get the properties
var properties = $(form).data('autosave');
switch(parameter){
case 'save':
var old_properties = $.extend({},properties);
//Set the new callbacks if they have been supplied
properties.options.success = typeof success!=='undefined' ? success : old_properties.options.success;
properties.options.error = typeof error!=='undefined' ? error : old_properties.options.error;
//Save the properties
$(form).data('autosave',properties);
//Call the save method before setting the interval
SM(form)._as_save();
properties = $.extend({},old_properties);
//Save the old properties
$(form).data('autosave',properties);
//Clear the current interval
clearInterval(properties.interval);
//Call the save method periodically
properties.interval = setInterval(function(){
SM(form)._as_save();
},properties.options.interval);
break;
}
//Save the properties
$(form).data('autosave',properties);
- Du sagst, dass nach
$('#foo').data('bar',old_options);
Sie sind immer noch zu sehenTemporary Function Called
? - Genau! 🙂
- Ich habe in der Tat
- Einige gute Antworten da unten.
- Ich bin ein wenig verwirrt - das neue update, war, dass nach unserer Diskussion über die flache Kopie gegen Tiefe Kopie? Ich sehe deine
success
Methode ist eigentlich eineoptions.success()
Methode (und Analog fürerror
). Das ist genau die situation, wo eine Tiefe Kopie erforderlich wäre. So sind die Dinge noch gebrochen, oder war der Tiefe Kopie den trick tun? - Nein, das kam vor 🙂 Die Tiefe es behoben
- Uff! Sie hatte mich besorgt an. Es macht Sinn, jetzt, Blick auf den code im update: Der flache Kopie gearbeitet haben würde, mit Ihrem code in der ursprünglichen Frage, wo die
success
Rückruf wurde ein first-level-Eigenschaft des main-options-Objekt. Aber der eigentliche code in Ihrem update ist ein bisschen anders: es hat eineproperties.options.success
Funktion - nicht ein direktes untergeordnetes Objekt, sondern zwei Stufen nach unten. Das ist genau die situation, in der eine Tiefe Kopie benötigt wird (oder zumindest eine mehr spezialisierte kopieren würde, Griff dieser verschachtelten Objekts).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie diesen code ausführen:
nicht ein kopieren des gesamten
options
Objekt, das können Sie später wiederherstellen. Sie sind lediglich das speichern einer Referenz der gleiche Objekt. In anderen Worten,old_options
ist, den gleichen Gegenstand wieoptions
, also, wenn Sie einen neuen Wert zuweisen inoptions.success
, Sie ändern es in beidenoptions
undold_options
—weil Sie das gleiche Objekt.Um dies zu beheben, können Sie ein Objekt Klonen Funktion, um eine Kopie des Objekts, die Sie dann später wiederherstellen. Da bist du mit jQuery, können Sie ändern Sie die obige Zeile:
Nun, wenn Sie ändern
options.success
bist du auch nur eine änderung imoptions
Objekt.old_options
ist unberührt, so dass Ihr später nennen wird es wieder erfolgreich:Interessant genug, das funktioniert zwar noch OK, auch wenn
options.success
ist eine asynchrone callback (das klingt wahrscheinlich aus dem Namen). Das ist, weil was auch immer code fordert, dass.success()
Methode später auf, sollten Sie noch auf halten, um einen Verweis auf Ihre geändertenoptions
Objekt—auch wenn Sie schon wieder die alte wieder in das element von Daten in der Zwischenzeit. Zumindest könnte man hoffen, dass, wenn der andere code gräbt sich zurück in die$().data()
zu finden, die.success
callback-dann würden Sie in Schwierigkeiten geraten.Den
$.extend()
Anruf über ein "tief" (rekursiv) kopieren deroptions
Objekt. Das heißt, wenn eine der Eigenschaften inoptions
ist selbst ein Objekt, es auch Klone, das Objekt-anstatt nur zu kopieren verwiesen.Wenn man die
true
argument$.extend()
hat eine flache Kopie statt:Diese noch erstellt ein neues Objekt und kopiert über alle Eigenschaften, die von einem vorhandenen Objekt, aber wenn eine dieser Eigenschaften ist selbst ein Objekt, die Sie gar nicht Klonen Sie dieses Objekt, es ist nur kopiert eine Referenz. Dies ist effizienter, wenn es funktioniert mit der Struktur des Objekts, das Sie verwenden, andernfalls können Sie die Tiefe Kopie.
Wenn die Eigenschaften/Methoden, die Sie brauchen, um zu retten und wiederherzustellen, sind direkte Kinder des main-Objekt, wird eine flache Kopie sollte reichen. Hier ist ein Fall, wo würden Sie definitiv benötigen eine Tiefe Kopie:
Hier haben wir ein Objekt mit einer
events
Eigenschaft, und diese Eigenschaft ist selbst ein Objekt mit einigen Eigenschaften/Methoden der eigenen (in diesem Beispiel einevents.success()
Methode. Wenn Sie eine flache Kopie des Objekts, das original und die Kopie wird teilen eine gemeinsameevents
Objekt. Also, wenn Sie so etwas Tat:Würden Sie wirklich aktualisiert werden, dass in beiden
options
undold_options
. Nicht gut. Das ist, wo eine Tiefe Kopie notwendig ist.extend
Methode?$('#foo').bar(options)
es erstellt eine Instanz von der bar. Und dann können Sie anrufen$('#foo').bar('save',function(){})
die Ausführung der save-Methode, und rufen Sie die callback-geliefert wird nur einmal und dann wieder zurück zu den spezifizierten callback in den ursprünglichen Instanzoptions
$.extend()
in dem moment, Sie schreiben, dass der Kommentar gefragt! Plus natürlich all die anderen Antworten sagen, die gleiche Sache. Ich denke, das alte Sprichwort ist zumindest teilweise wahr: great minds think alike. 🙂extend()
aber nicht denke, dass es einen Unterschied gemacht hätte... Wäre dieser Beitrag gelöscht, sobald ich sah Ihre Antwort, aber Sie hat so eine gute Ladung von rep aus, es dachte würde ich lassen Sie es 🙂success
Funktion und wenn Sie speichern, die Referenz für Ihre eigenen (später) verwenden. Vielleicht sind Sie OK, aber wie Sie sich vorstellen können, wenn ich höre "speichern und wiederherstellen Objekt/Funktion "Referenzen" und "Erfolgs-callback" (das klingt asynchron), im gleichen Atemzug beginne ich zu sorgen. 🙂complete
Funktion, die ausgeführt wird, und wiederherstellen der alten Einstellungen? Das Beispiel scheint, wie Sie es wünschen unabhängig.extend
nicht beheben... werfen Sie einen Blick auf mein update, um zu sehen, was ich eigentlich mache. Kann es sein, dass mir etwas fehlt offensichtlich...deep
parameter für diese, so sicher würde es Sortieren? Es nicht, wenn ich versuchte...$.extend(true,old_properties);
nicht$.extend(true,{},old_properties);
... nochmals vielen Dank!deep
option$.extend()
, danke für die Erinnerung. Ich bin überrascht, die erforderlich war, obwohl - es sei denn, es wurden andere verschachtelte Objekte? Aber in jedem Fall, wenn Sie haben es jetzt funktioniert, das ist cool! Es gibt keinen wirklichen Nachteil, der mit der Tiefe Kopie hier, auch wenn es nicht notwendig ist.Das problem ist, dass
options
hat Referenz-Semantik:Dieser Kommentar liegt. Sie müssen nicht eine Kopie der alten Optionen; vielmehr haben Sie eine andere Referenz auf das gleiche Objekt Optionen (ein anderer name, mit dem Sie nachlesen können).
So, wenn Sie Sie überschreiben
options.success
, ist diese änderung auch sichtbar aufold_options
. Der code, der verwendet.data
zum speichern und wiederherstellen der Wert der Optionen ist überflüssig.Das einzige, was Sie tun müssen, ist dieses:
options.success
...Wenn Sie dies tun
var old_options = options
du bist nicht kopierenoptions
Werte, sondern eine Referenz zu. Von nun anold_options
undoptions
zeigen Sie auf den gleichen Speicher-spot-und änderungen wirken sich auf beide.Ihr Problem ist, Sie arbeiten mit Objekte. Sie übergeben, um Verweise auf das Objekt. Das zugrunde liegende Objekt ist das gleiche, alles, was Sie getan haben, ist eine variable hinzuzufügen, die Punkte auf die gleiche Adresse.
Haben Sie zu Klonen Sie das Objekt. ZB erstellen Sie ein neues Objekt mit den gleichen Eigenschaften und kopieren Sie Sie auf.
Diese post für Sie nützlich sein kann.