JS-Objektkopie nach Wert und Kopie nach Referenz

8

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?

%Vor%     
RuntimeException 18.10.2013, 11:31
quelle

5 Antworten

11

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.

%Vor%     
Joseph 18.10.2013, 11:33
quelle
3

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:

  1. Boolesche
  2. Zahlen
  3. Zeichenfolgen
  4. Null
  5. Nicht definiert

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:

  1. Wir schreiben die Nummer 2 auf eine neue Notiz und legen sie auf unseren Kühlschrank.
  2. Wir kopieren die Nummer 2 von der Haftnotiz x auf eine andere Haftnotiz y und legen sie auf unseren Kühlschrank.
  3. Wir löschen den Wert der Haftnotiz y und schreiben stattdessen die Zahl 3 .
  4. Der Wert der Haftnotiz 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:

  1. Wir erstellen ein Objekt {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.
  2. Wir kopieren die Adresse 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.
  3. Wenn wir also den Wert von objA.a ändern, wird die gleiche Änderung in objB.a reflektiert, da objA und objB beide auf dasselbe Objekt verweisen, das am Speicherort x .
  4. gespeichert ist

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:

  1. Wir erstellen ein Objekt {a: 1} an einem Speicherort x und schreiben die Adresse x auf eine Kurznotiz objA .
  2. Wir kopieren die Adresse x von der Kurznotiz objA in die Kurznotiz objB . Beide zeigen nun auf das gleiche Objekt, das am Speicherort x .
  3. gespeichert ist
  4. Wir erstellen ein neues Objekt {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.

    
Aadit M Shah 18.10.2013 12:20
quelle
2

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.

%Vor%

Damit wird objA auf ein anderes Objekt ( {a:2} ) zeigen, während objB auf das alte Objekt zeigt.

    
closure 18.10.2013 11:33
quelle
1
  

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".)

    
Kos 18.10.2013 11:50
quelle
1

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.

    
webduvet 18.10.2013 11:37
quelle

Tags und Links