Ich habe eine Variable, deren Wert ein JSON-Objekt hat. Ich ordne diese Variable direkt einer anderen Variablen zu, damit sie denselben Wert haben. So funktioniert es:
var a = $('#some_hidden_var').val(),
b = a;
Dies funktioniert und beide haben den gleichen Wert. Ich verwende einen mousemove
Ereignishandler, um b
meine App zu aktualisieren . Bei einem Klick auf eine Schaltfläche möchte ich zum b
ursprünglichen Wert zurückkehren, dh zum Wert, der in gespeichert ist a
.
$('#revert').on('click', function(e){
b = a;
});
Wenn ich danach denselben mousemove
Ereignishandler verwende, werden beide a
und aktualisiertb
, wenn zuvor, nur b
wie erwartet aktualisiert .
Ich bin über dieses Problem ratlos! Was ist hier falsch?
javascript
jquery
Rutwick Gangurde
quelle
quelle
a
wurde, gehe.val()
ich davon aus, dass es sich um JSON (eine Zeichenfolge) und nicht um ein Objekt handelt - stimmt das? Verwenden SieJSON.parse(a)
irgendwann, um ein tatsächliches Objekt zu erhalten?$.parseJSON
, um sie in ein Objekt zu konvertieren. Struktur :{ 'key': {...}, 'key': {...}, ...}
. Leider kann hier kein Code gepostet werden, der an meinem Arbeitsplatz nicht erlaubt ist!a
also ein Objekt?a
eine globale Variable?$.parseJSON()
ist es schwer zu sagen, wo das Problem liegt, ohne mehr von dem Code zu sehen, der die Variablen manipuliert (wo kommt er hinein?). In Bezug auf Ihre Arbeitsplatzregeln müssen Sie Ihren tatsächlichen Code nicht vollständig veröffentlichen. Sie müssen lediglich ein kürzeres und allgemeineres Beispiel erstellen, das das Problem veranschaulicht (und im Idealfall einen Link zu einer Live-Demo auf jsfiddle.net enthalten ). .Antworten:
Es ist wichtig zu verstehen, was der
=
Operator in JavaScript tut und was nicht.Der
=
Betreiber erstellt keine Kopie der Daten.Der
=
Bediener erstellt einen neuen Verweis auf dieselben Daten.Nachdem Sie Ihren ursprünglichen Code ausgeführt haben:
a
undb
sind jetzt zwei verschiedene Namen für das gleiche Objekt .Jede Änderung, die Sie am Inhalt dieses Objekts vornehmen, wird identisch angezeigt, unabhängig davon, ob Sie über die
a
Variable oder die referenzierenb
Variable darauf . Sie sind das gleiche Objekt.Wenn Sie später versuchen, mit diesem Code
b
zum ursprünglichena
Objekt "zurückzukehren" :Der Code macht eigentlich gar nichts , weil
a
undb
genau das gleiche sind. Der Code ist der gleiche, als hätten Sie geschrieben:was offensichtlich nichts tun wird.
Warum funktioniert Ihr neuer Code?
Hier erstellen Sie ein brandneues Objekt mit dem
{...}
Objektliteral. Dieses neue Objekt ist nicht dasselbe wie Ihr altes Objekt. Sie stellen jetzt einb
als Referenz auf dieses neue Objekt, das macht, was Sie wollen.Um ein beliebiges Objekt zu verarbeiten, können Sie eine Objektklonfunktion wie die in Armands Antwort aufgeführte verwenden oder, da Sie jQuery verwenden, einfach die
$.extend()
Funktion verwenden . Diese Funktion erstellt entweder eine flache oder eine tiefe Kopie eines Objekts. (Verwechseln Sie dies nicht mit der$().clone()
Methode zum Kopieren von DOM-Elementen, nicht von Objekten.)Für eine flache Kopie:
Oder eine tiefe Kopie:
Was ist der Unterschied zwischen einer flachen und einer tiefen Kopie? Eine flache Kopie ähnelt Ihrem Code, der ein neues Objekt mit einem Objektliteral erstellt. Es wird ein neues Objekt der obersten Ebene erstellt, das Verweise auf dieselben Eigenschaften wie das ursprüngliche Objekt enthält.
Wenn Ihr Objekt nur primitive Typen wie Zahlen und Zeichenfolgen enthält, tun eine tiefe und eine flache Kopie genau dasselbe. Wenn Ihr Objekt jedoch andere darin verschachtelte Objekte oder Arrays enthält, kopiert eine flache Kopie diese verschachtelten Objekte nicht, sondern erstellt lediglich Verweise auf sie. Sie könnten also das gleiche Problem mit verschachtelten Objekten haben wie mit Ihrem Objekt der obersten Ebene. Zum Beispiel bei diesem Objekt:
Wenn Sie eine flache Kopie dieses Objekts erstellen, ist die
x
Eigenschaft Ihres neuen Objekts dasselbex
Objekt wie das Original:Jetzt sehen Ihre Objekte folgendermaßen aus:
Sie können dies mit einer tiefen Kopie vermeiden. Die tiefe Kopie wird in jedes verschachtelte Objekt und Array (und Datum in Armands Code) zurückgeführt, um Kopien dieser Objekte auf dieselbe Weise zu erstellen, wie sie eine Kopie des Objekts der obersten Ebene erstellt hat. Änderungen
copy.x.y
würden sich also nicht auswirkenobj.x.y
.Kurze Antwort: Im Zweifelsfall möchten Sie wahrscheinlich eine tiefe Kopie.
quelle
$.extend()
Funktion verwenden. Details oben. :-)Ich habe festgestellt, dass JSON funktioniert, aber achten Sie auf unsere Zirkelverweise
quelle
let a = {}; let b = {a:a}; a.b = b; JSON.stringify(a)
gibt einen TypeErrorDie Frage ist schon seit geraumer Zeit gelöst, aber für zukünftige Referenz ist eine mögliche Lösung
Seien Sie vorsichtig, dies funktioniert nur dann korrekt, wenn a ein nicht verschachteltes Array von Zahlen und Zeichenfolgen ist
quelle
newVariable = originalVariable.valueOf();
für Objekte, die Sie verwenden können,
b = Object.assign({},a);
quelle
Der Grund dafür ist einfach. JavaScript verwendet Referenzen. Wenn Sie also zuweisen, weisen
b = a
Sie einen Verweis zu , sodass Sieb
beim Aktualisierena
auch aktualisierenb
Ich habe dies bei Stackoverflow gefunden und werde helfen, solche Dinge in Zukunft zu verhindern, indem ich nur diese Methode aufrufe, wenn Sie eine tiefe Kopie eines Objekts erstellen möchten.
quelle
if (obj instanceof x) { ... }
anders sein, wenn?Ich verstehe nicht, warum die Antworten so komplex sind. In Javascript werden Grundelemente (Zeichenfolgen, Zahlen usw.) als Wert übergeben und kopiert. Objekte, einschließlich Arrays, werden als Referenz übergeben. In jedem Fall ändert die Zuweisung eines neuen Wertes oder einer neuen Objektreferenz zu 'a' nichts an 'b'. Durch Ändern des Inhalts von 'a' wird jedoch der Inhalt von 'b' geändert.
Fügen Sie eine der oben genannten Zeilen (einzeln) in einen Knoten oder eine Browser-Javascript-Konsole ein. Geben Sie dann eine beliebige Variable ein und die Konsole zeigt ihren Wert an.
quelle
Für Zeichenfolgen oder Eingabewerte können Sie einfach Folgendes verwenden:
quelle
Die meisten Antworten hier verwenden integrierte Methoden oder Bibliotheken / Frameworks. Diese einfache Methode sollte gut funktionieren:
quelle
Object.assign({},a)
Ich habe es vorerst selbst gelöst. Der ursprüngliche Wert hat nur 2 Untereigenschaften. Ich habe ein neues Objekt mit den Eigenschaften von reformiert
a
und es dann zugewiesenb
. Jetzt wird mein Event-Handler nur noch aktualisiertb
und mein Originala
bleibt unverändert.Das funktioniert gut. Ich habe keine einzige Zeile in meinem Code geändert, außer den oben genannten, und es funktioniert genau so, wie ich es wollte. Also, vertrau mir, nichts anderes wurde aktualisiert
a
.quelle
Eine Lösung für AngularJS :
quelle