Also habe ich neulich herumgespielt, um genau zu sehen, wie die Massenzuweisung in JavaScript funktioniert.
Zuerst habe ich dieses Beispiel in der Konsole ausprobiert:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
Das Ergebnis war, dass "Balken" in einer Warnung angezeigt wurde. Das ist fair genug a
und b
wirklich nur Aliase für dasselbe Objekt. Dann dachte ich, wie könnte ich dieses Beispiel einfacher machen.
a = b = 'foo';
a = 'bar';
console.log(b);
Das ist so ziemlich das Gleiche, nicht wahr? Nun, diesmal kehrt es foo
nicht bar
so zurück , wie ich es vom Verhalten des ersten Beispiels erwarten würde.
Warum passiert das?
NB Dieses Beispiel könnte mit dem folgenden Code noch weiter vereinfacht werden:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(Ich vermute, dass JavaScript Primitive wie Zeichenfolgen und Ganzzahlen anders behandelt als Hashes. Hashes geben einen Zeiger zurück, während "Core" -Primitive eine Kopie von sich selbst zurückgeben.)
quelle
Antworten:
Im ersten Beispiel legen Sie eine Eigenschaft eines vorhandenen Objekts fest. Im zweiten Beispiel weisen Sie ein brandneues Objekt zu.
a
undb
sind jetzt Zeiger auf dasselbe Objekt. Also, wenn Sie tun:Es setzt
b.foo
auch daa
und zeigtb
auf dasselbe Objekt.Jedoch!
Wenn Sie dies stattdessen tun:
Sie sagen, das
a
zeigt jetzt auf ein anderes Objekt. Dies hat keine Auswirkung auf das, worauf zuvora
hingewiesen wurde.In JavaScript sind das Zuweisen einer Variablen und das Zuweisen einer Eigenschaft zwei verschiedene Operationen. Stellen Sie sich Variablen am besten als Zeiger auf Objekte vor. Wenn Sie einer Variablen direkt zuweisen, ändern Sie keine Objekte, sondern ordnen Ihre Variable lediglich einem anderen Objekt zu.
Durch das Zuweisen einer Eigenschaft wie
a.foo
wird jedoch das Objekt geändert, auf das verwiesen wirda
. Dadurch werden natürlich auch alle anderen Verweise geändert, die auf dieses Objekt verweisen, nur weil sie alle auf dasselbe Objekt verweisen.quelle
var foo = new String('foo');
, dann , dass wäre ein String - Objekt (undtypeof
bestätigt dies). Wenn Sie es jedoch über ein Zeichenfolgenliteral deklarieren, handelt es sich um Zeichenfolgenprimitive. Siehe: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…Ihre Frage wurde von Squeegy bereits zufriedenstellend beantwortet - sie hat nichts mit Objekten vs. Grundelementen zu tun, sondern mit der Neuzuweisung von Variablen vs. Festlegen von Eigenschaften in demselben referenzierten Objekt.
Die Antworten und Kommentare scheinen viel Verwirrung über JavaScript-Typen zu stiften. Hier eine kleine Einführung in das JavaScript-Typsystem:
In JavaScript gibt es zwei grundlegend unterschiedliche Arten von Werten: Grundelemente und Objekte (und es gibt nichts Vergleichbares wie einen 'Hash').
Zeichenfolgen, Zahlen und Boolesche Werte sowie
null
undundefined
sind Grundelemente. Objekte sind alles, was Eigenschaften haben kann. Sogar Arrays und Funktionen sind reguläre Objekte und können daher beliebige Eigenschaften enthalten. Sie unterscheiden sich nur in der internen Eigenschaft [[Klasse]] (Funktionen haben zusätzlich eine Eigenschaft namens [[Aufruf]] und [[Konstrukt]], aber hey, das sind Details).Der Grund dafür, dass sich primitive Werte wie Objekte verhalten, liegt im Autoboxing, aber die primitiven Werte selbst können keine Eigenschaften enthalten.
Hier ist ein Beispiel:
Dies gibt Folgendes aus
undefined
:a
Enthält einen primitiven Wert, der beim Zuweisen der Eigenschaft zu einem Objekt heraufgestuft wirdfoo
. Dieses neue Objekt wird jedoch sofort verworfen, sodass der Wert vonfoo
verloren geht.Stellen Sie sich das so vor:
quelle
Sie sind mehr oder weniger korrekt, außer dass das, was Sie als "Hash" bezeichnen, eigentlich nur eine Kurzsyntax für ein Objekt ist.
Im ersten Beispiel beziehen sich a und b beide auf dasselbe Objekt. Im zweiten Beispiel ändern Sie a , um auf etwas anderes zu verweisen.
quelle
Hier ist meine Version der Antwort:
quelle
Sie setzen a so, dass es auf ein neues Zeichenfolgenobjekt zeigt, während b weiterhin auf das alte Zeichenfolgenobjekt zeigt.
quelle
Im ersten Fall ändern Sie eine Eigenschaft des in der Variablen enthaltenen Objekts, im zweiten Fall weisen Sie der Variablen einen neuen Wert zu. Das sind grundsätzlich verschiedene Dinge. Die Variablen
a
undb
sind nicht irgendwie magisch durch die erste Zuweisung verknüpft, sie enthalten nur das gleiche Objekt. Dies ist auch im zweiten Beispiel der Fall, bis Sie derb
Variablen einen neuen Wert zuweisen .quelle
Der Unterschied besteht zwischen einfachen Typen und Objekten.
Alles, was ein Objekt ist (wie ein Array oder eine Funktion), wird als Referenz übergeben.
Alles, was ein einfacher Typ ist (wie eine Zeichenfolge oder eine Zahl), wird kopiert.
Ich habe immer eine copyArray-Funktion zur Hand, damit ich sicher sein kann, dass ich keine Aliase für dasselbe Array erstelle.
quelle