Ich spielte mit der Chrome-Konsole und bemerkte etwas, das ich nicht verstehen konnte. Ich weiß in JS Variablen werden nach Wert kopiert und Objekte werden als Referenz kopiert. Der folgende Code funktioniert wie erwartet, er gibt 2 aus und beweist, dass JS-Objekte als Referenz funktionieren:
%Vor% Dieser Code funktioniert jedoch nicht so, wie er sollte. Ich habe erwartet, dass objB.a 2
ausgibt, aber stattdessen 1
. Warum?
Ich würde eher auf Variablen mit Objekten als Zeiger auf Objekte (wie C-Zeiger) anstatt auf Referenzen achten.
In Ihrer dritten Zeile haben Sie gerade objA
ersetzt, sodass Sie auf ein anderes Objekt zeigen. Es ändert sich nicht was auch immer objB
"zeigt".
Nach Zeile 3 zeigt objA
jetzt auf {a:2}
, während objB
immer noch auf die objA
zeigt, die auf die Zeit zeigt, als Sie sie objB
zugewiesen haben, in Zeile 2, was {a:1}
ist.
Ich denke gerne an JavaScript-Variablen als Haftnotizen . Eine Notiz ist eine kleine Notiz, die Sie auf Ihren Kühlschrank legen. Was kannst du auf deine Notiz schreiben? Sie können kleine Informationen schreiben.
Jetzt gibt es zwei Arten von Informationen in JavaScript - primitive Werte und Referenzwerte. Primitive Werte sind kleine Informationen, die Sie direkt auf Ihre Notiz schreiben können. Dazu gehören:
Andererseits sind Referenzwerte große Mengen von Informationen, die Sie nicht auf eine kleine Notiz schreiben können. Wie speichern Sie Referenzwerte in Haftnotizen?
Sie nicht.
Referenzwerte (wie Arrays, Objekte und Funktionen) werden auf ein größeres Stück Papier geschrieben und nur ein Verweis auf sie wird auf die Notiz geschrieben. Zum Beispiel könnte meine Frau schreiben:
Liebling, die Liste der Lebensmittel steht unter Ihrer Tastatur.
Hier ist die Liste der Lebensmittel ein Array (d. h. eine große Menge an Informationen). Da wir es nicht auf eine kleine Notiz schreiben können, schreiben wir es einfach auf ein größeres Stück Papier und machen eine Notiz, die uns sagt, wo es zu finden ist. Programmiert ausgedrückt:
%Vor% Hier wird die eigentliche Einkaufsliste irgendwo im Speicher abgelegt und nur die Adresse der Einkaufsliste wird in der Variable groceryList
gespeichert.
Was passiert also, wenn wir eine Variable einer anderen zuweisen? Nehmen wir zuerst ein Beispiel für einen primitiven Wert:
%Vor%Das ist was passiert:
2
auf eine neue Notiz und legen sie auf unseren Kühlschrank. 2
von der Haftnotiz x
auf eine andere Haftnotiz y
und legen sie auf unseren Kühlschrank. y
und schreiben stattdessen die Zahl 3
. x
ist 2
und die Haftnotiz y
ist 3
. Dies wird als Kopie nach Wert bezeichnet, da wir nur den Wert der Haftnotiz x
auf die Haftnotiz y
kopieren.
Nehmen wir nun ein Beispiel für eine Kopie als Referenz. In der Tat nehmen wir Ihr Exemplar als Referenz:
%Vor%Hier ist, was in Ihrem Beispiel passiert:
{a: 1}
irgendwo im Speicher und schreiben die Adresse dieses Objekts in die Notiz objA
. Lassen Sie uns der Einfachheit halber diese Adresse x
nennen. x
von der Haftnotiz objA
auf eine andere Haftnotiz objB
. Nun verweisen sowohl objA
als auch objB
auf das gleiche Objekt {a: 1}
, das am Speicherort x
gespeichert ist. objA.a
ändern, wird die gleiche Änderung in objB.a
reflektiert, da objA
und objB
beide auf dasselbe Objekt verweisen, das am Speicherort x
. Dies wird Kopieren als Referenz genannt, weil wir einfach die Referenz eines Objekts von der Haftnotiz objA
in die Haftnotiz objB
kopieren. Wir kopieren nicht das tatsächliche Objekt.
Was ist der Unterschied zwischen Kopieren nach Referenz und Kopieren nach Wert? Absolut gar nichts. In beiden Fällen kopieren wir einfach den Wert einer Notiz auf einen anderen.
Zwei Haftnotizen sollen nur dann äquivalent sein, wenn sie genau dieselben Informationen enthalten. Zum Beispiel sind die folgenden gleichwertig:
%Vor%Die folgenden Werte sind jedoch nicht gleichwertig:
%Vor% Der Grund, dass sie nicht äquivalent sind, liegt darin, dass o
auf ein Objekt verweist, das an einem Speicherort gespeichert ist, zB x
, während p
auf ein Objekt verweist, das an einem anderen Speicherort gespeichert ist, zB y
. Obwohl beide Objekte die gleichen Eigenschaften haben, sind sie tatsächlich zwei verschiedene Objekte.
Zum Beispiel sind keine zwei Nintendo Gameboys gleich, egal wie identisch sie aussehen. Sehen wir uns im gleichen Sinne Ihr letztes Beispiel an:
%Vor%Hier ist was passiert in dem obigen Code:
{a: 1}
an einem Speicherort x
und schreiben die Adresse x
auf eine Kurznotiz objA
. x
von der Kurznotiz objA
in die Kurznotiz objB
. Beide zeigen nun auf das gleiche Objekt, das am Speicherort x
. {a: 2}
an einem Speicherort y
und schreiben die Adresse y
auf die Sticknote objA
. Jetzt hat objA
einen Referenzwert y
und objB
hat einen Referenzwert x
. Sie verweisen auf zwei verschiedene Objekte. Wie Sie sehen, wird objA
einen neuen Referenzwert zuweisen, indem einfach der alte Referenzwert überschrieben wird. Es ersetzt nicht das Objekt {a: 1}
mit dem Objekt {a: 2}
. Das ist in JavaScript nicht möglich.
Ihr erstes Beispiel funktioniert als Objekt, auf das beide Variablen zeigen .
In Ihrem zweiten Beispiel nicht, weil Sie ein anderes Objekt an objA
at line #3
zuweisen.
Damit wird objA
auf ein anderes Objekt ( {a:2}
) zeigen, während objB
auf das alte Objekt zeigt.
Ich spielte mit der Chrome-Konsole und bemerkte etwas, das ich nicht verstehen konnte. Ich weiß in JS Variablen werden nach Wert kopiert und Objekte werden durch Referenz kopiert.
Nein. Es gibt auch keine "Kopieren nach Wert" oder "Kopieren durch Referenz", es gibt nur "Kopieren".
Der Wert einer Variablen bezieht sich immer auf ein Objekt. Das Objekt kann vom Typ Object
sein, wie {}
, oder vom Typ Nummer, wie 5
oder einem anderen.
Der Zuweisungs- und Funktionsaufruf kopiert niemals Objekte in Javascript, sondern bindet nur denselben Wert an eine andere Variable:
%Vor%Das Kopieren von Objekten muss explizit von Ihnen, Objekten, erfolgen werde nicht magisch kopiert.
Das Kopieren von Object
s ist sinnvoll, weil ein Object
geändert werden kann. Das Kopieren von Zahlen oder Strings ist jedoch nicht sinnvoll - es interessiert Sie nur, dass sich der Wert einer Variablen auf 1234
bezieht, aber Sie würden sich nie "für welche 1234" interessieren. (Sie haben keine "Identität".)
ObjB zeigt in Ihrem Fall nicht auf die Variable objA, sondern auf das Objekt, auf das das darstellbare Objekt projiziert. Das Ändern der Objekteigenschaften ist also nicht dasselbe wie das Ändern der Position der Variablen.
In JavaScript werden Variablen nach Wert übergeben. Bei Objekten ist es nicht anders. Die Variable ist kein Zeiger auf das Objekt, wie in C ++. Es enthält nur einen Verweis auf den Zeiger, der nur von Javascript selbst zugänglich ist. Also wenn du es tust:
%Vor%Sie kopieren nur den Referenzzeiger auf das Objekt im Speicher.
Tags und Links javascript