Die primitiven Typen (Zahl, Zeichenfolge usw.) werden als Wert übergeben, Objekte sind jedoch unbekannt, da sie beide als Wert übergeben werden können (falls wir davon ausgehen, dass eine Variable, die ein Objekt enthält, tatsächlich eine Referenz auf das Objekt ist ) und als Referenz übergeben (wenn wir bedenken, dass die Variable zum Objekt das Objekt selbst enthält).
Obwohl es am Ende nicht wirklich wichtig ist, möchte ich wissen, wie die Argumente, die Konventionen verabschieden, richtig präsentiert werden. Gibt es einen Auszug aus der JavaScript-Spezifikation, der definiert, wie die Semantik dazu aussehen soll?
javascript
pass-by-reference
pass-by-value
Danail Nachev
quelle
quelle
var x=3, y=x; f(x); alert(y === x);
dann Funktion habenf()
, der Alarmbericht erstellt werden kannfalse
und nichttrue
. In JavaScript ist dies nicht möglich, daher wird es nicht als Referenz übergeben. Es ist gut, dass es möglich ist, Verweise auf veränderbare Objekte zu übergeben, aber das ist nicht das, was "Referenzübergabe" bedeutet. Wie gesagt, es ist eine Schande, dass die Terminologie so verwirrend ist.Antworten:
Es ist interessant in JavaScript. Betrachten Sie dieses Beispiel:
Dies erzeugt die Ausgabe:
obj1
keine Referenzobj1.item
wäre, hätte eine Änderung keine Auswirkung auf dieobj1
Außenseite der Funktion.num
wäre100
undobj2.item
würde lesen"changed"
.Stattdessen wird das übergebene Element als Wert übergeben. Das Element, das als Wert übergeben wird, ist selbst eine Referenz. Technisch wird dies als Call-by-Sharing bezeichnet .
In der Praxis bedeutet dies, dass sich das Ändern des Parameters selbst (wie bei
num
undobj2
) nicht auf das Element auswirkt, das in den Parameter eingegeben wurde. Wenn Sie jedoch die INTERNEN des Parameters ändern , wird dies (wie beiobj1
) wieder weitergegeben.quelle
item
Eigenschaft des Objekts ändern, auf das obj1 verweist, ändern Sie den Wert der Elementeigenschaft, die ursprünglich auf "unverändert" festgelegt wurde. Wenn Sie obj2 den Wert {item: "defined"} zuweisen, ändern Sie den Verweis auf ein neues Objekt (das beim Beenden der Funktion sofort den Gültigkeitsbereich verlässt). Es wird deutlicher, was passiert, wenn Sie die Funktionsparameter wie numf, obj1f und obj2f benennen. Dann sehen Sie, dass die Parameter die externen Variablennamen versteckten.ref
Schlüsselwort angeben .) Normalerweise muss die Funktion nur das neue Objekt zurückgeben und dies tun die Zuordnung an der Stelle, an der Sie die Funktion aufrufen. ZBfoo = GetNewFoo();
stattGetNewFoo(foo);
var obj1 = { item: 'unchanged' }; var obj2 = obj1; obj2.item = 'changed';
und würden den gleichen Effekt wie in Ihrem Beispiel beobachten. Deshalb verweise ich persönlich auf die Antwort von Tim GoodmanEs wird immer als Wert übergeben, aber für Objekte ist der Wert der Variablen eine Referenz. Wenn Sie ein Objekt übergeben und seine Mitglieder ändern , bleiben diese Änderungen daher außerhalb der Funktion bestehen. Dadurch sieht es so aus, als würde man als Referenz übergeben. Wenn Sie jedoch den Wert der Objektvariablen tatsächlich ändern, werden Sie feststellen, dass die Änderung nicht fortbesteht, was beweist, dass sie tatsächlich als Wert übergeben wird.
Beispiel:
Ausgabe:
quelle
changeObject
habe ich geändertx
, um einen Verweis auf das neue Objekt zu enthalten.x = {member:"bar"};
entsprichtx = new Object(); x.member = "bar";
übrigens dem , was ich sage, auch für C #.ref
Schlüsselwort verwenden, können Sie die Referenz als Referenz übergeben (anstelle der Standardeinstellung, die Referenz als Wert zu übergeben), und die Änderung, auf a zu zeigen,new Object()
bleibt bestehen .Die Variable "hält" das Objekt nicht; es enthält eine Referenz. Sie können diese Referenz einer anderen Variablen zuweisen, und jetzt verweisen beide auf dasselbe Objekt. Es wird immer als Wert übergeben (auch wenn dieser Wert eine Referenz ist ...).
Es gibt keine Möglichkeit, den Wert einer als Parameter übergebenen Variablen zu ändern. Dies wäre möglich, wenn JavaScript die Übergabe als Referenz unterstützt.
quelle
Meine zwei Cent ... So verstehe ich es. (Fühlen Sie sich frei, mich zu korrigieren, wenn ich falsch liege)
Es ist Zeit, alles, was Sie über Pass by Value / Reference wissen, wegzuwerfen.
Denn in JavaScript spielt es keine Rolle, ob es als Wert oder als Referenz oder was auch immer übergeben wird. Was zählt, ist die Mutation gegen die Zuordnung der an eine Funktion übergebenen Parameter.
OK, lassen Sie mich mein Bestes geben, um zu erklären, was ich meine. Angenommen, Sie haben einige Objekte.
Was wir getan haben, ist "Zuweisung" ... Wir haben den Variablen "Objekt1" und "Objekt2" 2 separate leere Objekte zugewiesen.
Nehmen wir nun an, wir mögen object1 besser ... Also "weisen" wir eine neue Variable zu.
Als nächstes entscheiden wir aus irgendeinem Grund, dass uns Objekt 2 besser gefällt. Also machen wir einfach eine kleine Neuzuweisung.
Objekt1 oder Objekt2 ist nichts passiert. Wir haben überhaupt keine Daten geändert. Wir haben lediglich neu zugewiesen, was unser Lieblingsobjekt ist. Es ist wichtig zu wissen, dass Objekt2 und Favoritenobjekt beide demselben Objekt zugewiesen sind. Wir können dieses Objekt über eine dieser Variablen ändern.
OK, jetzt schauen wir uns Primitive wie zum Beispiel Strings an
Wieder wählen wir einen Favoriten.
Sowohl unsere Favoriten-Variablen stringString als auch string1 sind 'Hello world' zugeordnet. Was ist, wenn wir unseren Favoriten ändern wollen? Was wird passieren???
Oh oh ... was ist passiert? Wir konnten string1 nicht ändern, indem wir favorString geändert haben ... Warum? Weil wir unser String- Objekt nicht geändert haben . Alles, was wir getan haben, war "RE ASSIGN", die Variable "avorString " für einen neuen String. Dies trennte es im Wesentlichen von string1. Im vorherigen Beispiel haben wir beim Umbenennen unseres Objekts nichts zugewiesen. (Nun, nicht der Variablen selbst , ... wir haben jedoch die Eigenschaft name einer neuen Zeichenfolge zugewiesen.) Stattdessen haben wir einfach das Objekt mutiert, das die Verbindungen zwischen den beiden Variablen und den zugrunde liegenden Objekten beibehält. (Auch wenn wir das String-Objekt selbst ändern oder mutieren wollten, konnten wir nicht haben, weil Strings in JavaScript tatsächlich unveränderlich sind.)
Nun zu Funktionen und Übergabe von Parametern ... Wenn Sie eine Funktion aufrufen und einen Parameter übergeben, tun Sie im Wesentlichen eine "Zuweisung" zu einer neuen Variablen, und dies funktioniert genauso, als ob Sie einfach mit zugewiesen hätten das Gleichheitszeichen (=).
Nehmen Sie diese Beispiele.
Nun das Gleiche, aber mit einer Funktion
OK, jetzt geben wir ein paar Beispiele, die stattdessen Objekte verwenden ... zuerst ohne die Funktion.
Nun das Gleiche, aber mit einem Funktionsaufruf
OK, wenn Sie diesen gesamten Beitrag durchlesen, haben Sie jetzt vielleicht ein besseres Verständnis dafür, wie Funktionsaufrufe in JavaScript funktionieren. Es spielt keine Rolle, ob etwas als Referenz oder als Wert übergeben wird ... Was zählt, ist Zuordnung gegen Mutation.
Jedes Mal, wenn Sie eine Variable an eine Funktion übergeben, "weisen" Sie dem Namen der Parametervariablen "zu", genau wie wenn Sie das Gleichheitszeichen (=) verwendet haben.
Denken Sie immer daran, dass das Gleichheitszeichen (=) Zuweisung bedeutet. Denken Sie immer daran, dass das Übergeben eines Parameters an eine Funktion in JavaScript auch eine Zuweisung bedeutet. Sie sind gleich und die beiden Variablen sind genau gleich miteinander verbunden (dh sie sind es nicht, es sei denn, Sie zählen, dass sie demselben Objekt zugewiesen sind).
Das "Ändern einer Variablen" wirkt sich nur dann auf eine andere Variable aus, wenn das zugrunde liegende Objekt mutiert ist (in diesem Fall haben Sie nicht die Variable, sondern das Objekt selbst geändert.
Es macht keinen Sinn, zwischen Objekten und Grundelementen zu unterscheiden, da dies genauso funktioniert, als ob Sie keine Funktion hätten und nur das Gleichheitszeichen verwendet hätten, um einer neuen Variablen zuzuweisen.
Das einzige Problem ist, wenn der Name der Variablen, die Sie an die Funktion übergeben, mit dem Namen des Funktionsparameters übereinstimmt. In diesem Fall müssen Sie den Parameter in der Funktion so behandeln, als wäre er eine ganz neue Variable, die für die Funktion privat ist (weil dies der Fall ist).
quelle
foo(char *a){a="hello";}
tut nichts, aber wenn Sie dies tun, wirdfoo(char *a){a[0]='h';a[1]='i';a[2]=0;}
es außerhalb geändert, daa
ein Speicherort als Wert übergeben wird, der auf eine Zeichenfolge verweist (char-Array). Das Übergeben von Strukturen (ähnlich wie bei js-Objekten) als Wert in C ist zulässig, wird jedoch nicht empfohlen. JavaScript setzt diese Best Practices einfach durch und verbirgt die unnötigen und normalerweise unerwünschten Cruft ... und erleichtert das Lesen.source = { "id":"1"}; copy = source /*this is wrong*/; copy.id="2"
dass diese Quelle immer noch {"id": "1"} ist?Folgendes berücksichtigen:
Also,
vergessen Sie „Pass von reference / Wert“nicht auf aufgehängt bekommen „vorbei reference / Wert“ , weil:Um Ihre Frage zu beantworten: Zeiger werden übergeben.
Einige abschließende Kommentare:
quelle
{'George', 1}
Werte durchlaufe , aber jeweils nur einen davon verwende, wie werden dann die anderen verwaltet? Und was passiert, wenn ich dem Wert einer anderen Variablen eine Variable zuordne? Zeige ich dann auf einen Zeiger oder auf den Zeiger des richtigen Operanden? Hatvar myExistingVar = {"blah", 42}; var obj = myExistingVar;
Ergebnis inobj
zeigt auf{"blah", 42}
, odermyExistingVar
?1)
ich in den Browser-Entwicklungstools ein Speicherprofil für eine Schleifenfunktion wie die von Ihnen beschriebene ausgeführt und während des gesamten Schleifenprozesses Spitzen in der Speichernutzung festgestellt. Dies scheint darauf hinzudeuten, dass in jeder Iteration der Schleife tatsächlich neue identische Objekte erstellt werden. Wenn die Stacheln plötzlich fallen, hat der Müllsammler gerade eine Gruppe dieser nicht verwendeten Objekte aufgeräumt.2)
In Bezug auf so etwasvar a = b
bietet Javascript keinen Mechanismus für die Verwendung von Zeigern, sodass eine Variable niemals auf einen Zeiger verweisen kann (wie in C), obwohl die zugrunde liegende Javascript-Engine sie zweifellos verwendet. Also ...var a = b
wirda
"auf den Pointee des richtigen Operanden" zeigenEin Objekt außerhalb einer Funktion wird an eine Funktion übergeben, indem auf das externe Objekt verwiesen wird.
Wenn Sie diese Referenz verwenden, um das Objekt zu bearbeiten, ist das Objekt außerhalb davon betroffen. Wenn Sie sich jedoch innerhalb der Funktion entschieden haben, den Verweis auf etwas anderes zu verweisen, haben Sie das Objekt außerhalb überhaupt nicht beeinflusst, da Sie lediglich den Verweis auf etwas anderes umgeleitet haben.
quelle
Stellen Sie sich das so vor: Es geht immer um Wert. Der Wert eines Objekts ist jedoch nicht das Objekt selbst, sondern ein Verweis auf dieses Objekt.
Hier ist ein Beispiel für die Übergabe einer Zahl (ein primitiver Typ).
Wenn Sie dies mit einem Objekt wiederholen, erhalten Sie unterschiedliche Ergebnisse:
Noch ein Beispiel:
quelle
Eine sehr detaillierte Erklärung zum Kopieren, Übergeben und Vergleichen nach Wert und Referenz finden Sie in diesem Kapitel des Buches "JavaScript: The Definitive Guide" .
quelle
JavaScript wird immer als Wert übergeben . Alles ist vom Werttyp.
Objekte sind Werte, und Elementfunktionen von Objekten sind selbst Werte (denken Sie daran, dass Funktionen in JavaScript erstklassige Objekte sind). Auch in Bezug auf das Konzept, dass alles in JavaScript ein Objekt ist ; das ist falsch. Streicher, Symbole, Zahlen, Boolesche Werte, Nullen und undefineds sind Primitiven .
Gelegentlich können sie einige Mitgliedsfunktionen und -eigenschaften nutzen, die von ihren Basisprototypen geerbt wurden. Dies dient jedoch nur der Bequemlichkeit. Dies bedeutet nicht, dass sie selbst Objekte sind. Versuchen Sie Folgendes als Referenz:
In beiden Warnungen finden Sie den Wert als undefiniert.
quelle
x = "teste"; x.foo = 12;
usw. Nur weil eine Eigenschaft nicht persistent ist, heißt das nicht, dass sie kein Objekt ist. Wie MDN sagt: In JavaScript ist fast alles ein Objekt. Alle primitiven Typen außer null und undefiniert werden als Objekte behandelt. Ihnen können Eigenschaften zugewiesen werden (zugewiesene Eigenschaften einiger Typen sind nicht persistent) und sie haben alle Eigenschaften von Objekten. LinkIn JavaScript steuert der Werttyp ausschließlich , ob dieser Wert durch Wertkopie oder Referenzkopie zugewiesen wird .
Primitive Werte werden immer von value-copy zugewiesen / übergeben :
null
undefined
ES6
Zusammengesetzte Werte werden immer per Referenzkopie zugewiesen / übergeben
Zum Beispiel
Da
2
es sich bei dem obigen Snippet um ein skalares Grundelement handelt,a
enthält es eine erste Kopie dieses Werts undb
erhält eine weitere Kopie des Werts. Beim Ändern ändernb
Sie in keiner Weise den Wert ina
.Aber beide
c
undd
sind separate Verweise auf denselben gemeinsamen Wert[1,2,3]
, der ein zusammengesetzter Wert ist. Es ist wichtig zu beachten, dass wederc
nochd
mehr den[1,2,3]
Wert "besitzen" - beide sind nur gleiche Peer-Verweise auf den Wert. Wenn Sie also eine der Referenzen verwenden, um.push(4)
den tatsächlichen gemeinsamenarray
Wert selbst zu ändern ( ) , wirkt sich dies nur auf den einen gemeinsamen Wert aus, und beide Referenzen verweisen auf den neu geänderten Wert[1,2,3,4]
.Wenn wir die Zuweisung vornehmen
b = [4,5,6]
, tun wir absolut nichts, um zu beeinflussen, woa
noch referenziert wird ([1,2,3]
). Um dies zu tun,b
müsste es eher ein Zeigera
als ein Verweis auf das seinarray
- aber in JS gibt es keine solche Fähigkeit!Wenn wir das Argument übergeben
a
, weist es eine Kopie desa
Verweises zux
.x
unda
sind separate Referenzen, die auf denselben[1,2,3]
Wert verweisen . Jetzt können wir innerhalb der Funktion diese Referenz verwenden, um den Wert selbst zu mutieren (push(4)
). Wenn wir die Zuweisung vornehmenx = [4,5,6]
, hat dies jedoch keinen Einfluss darauf, wohin die ursprüngliche Referenza
zeigt - zeigt immer noch auf den (jetzt geänderten)[1,2,3,4]
Wert.Um einen zusammengesetzten Wert (wie einen
array
) effektiv als Wertkopie zu übergeben, müssen Sie manuell eine Kopie davon erstellen, damit die übergebene Referenz nicht immer noch auf das Original verweist. Zum Beispiel:Zusammengesetzter Wert (Objekt, Array usw.), der per Referenzkopie übergeben werden kann
Hier
obj
fungiert es als Wrapper für die skalare primitive Eigenschafta
. Bei der Übergabe anfoo(..)
wird eine Kopie derobj
Referenz übergeben und auf denwrapper
Parameter gesetzt. Wir können jetzt diewrapper
Referenz verwenden, um auf das freigegebene Objekt zuzugreifen und seine Eigenschaft zu aktualisieren. Nach Abschluss der Funktionobj.a
wird der aktualisierte Wert angezeigt42
.Quelle
quelle
Nun, es geht um "Leistung" und "Geschwindigkeit" und um das einfache Wort "Speicherverwaltung" in einer Programmiersprache.
In Javascript können wir Werte in zwei Ebenen einfügen : Typ1 -
objects
und Typ2 - alle anderen Werttypen wiestring
&boolean
& etc.Wenn Sie sich Speicher wie unter Quadraten vorstellen, in denen in jedem von ihnen nur ein Typ2-Wert gespeichert werden kann:
Jeder Typ2-Wert (grün) ist ein einzelnes Quadrat, während ein Typ1-Wert (blau) eine Gruppe davon ist :
Der Punkt ist, dass, wenn Sie einen Typ2-Wert angeben möchten, die Adresse einfach ist, aber wenn Sie dasselbe für den Typ1-Wert tun möchten, ist das überhaupt nicht einfach! ::
und in einer komplizierteren Geschichte:
Hier können uns Referenzen retten:
Während der grüne Pfeil hier eine typische Variable ist, ist der lila Pfeil eine Objektvariable. Da der grüne Pfeil (typische Variable) nur eine Aufgabe hat (und dies zeigt einen typischen Wert an), müssen wir seinen Wert nicht von diesem trennen es so bewegen wir den grünen Pfeil mit dem Wert davon, wohin es geht und in allen Aufgaben, Funktionen und so weiter ...
Aber wir können nicht dasselbe mit dem lila Pfeil machen. Vielleicht möchten wir die 'John'-Zelle hierher bewegen oder viele andere Dinge ..., damit der lila Pfeil an seiner Stelle bleibt und nur typische Pfeile, die ihm zugewiesen wurden, sich bewegen ...
In einer sehr verwirrenden Situation können Sie nicht erkennen, wie sich Ihre referenzierte Variable ändert. Schauen wir uns ein sehr gutes Beispiel an:
quelle
Dies ist kaum eine Erklärung für die Übergabe von Wert und Übergabe als Referenz (JavaScript). In diesem Konzept geht es darum, die Variable als Referenz und die Variable als Referenz zu übergeben.
Wert übergeben (primitiver Typ)
Referenzübergabe (Objekte)
c
und zeigt auf etwas Speicher, z. B. (0x012).d
auf dieselbe Stelle (0x012).Sonderfall, Referenzübergabe (Objekte)
quelle
c
wird auf eine Kopie der Referenz des neuen Objekts festgelegt.Wenn Sie in JavaScript einer Variablen ein Objekt zuweisen, ist der der Variablen zugewiesene Wert eine Referenz auf das Objekt:
quelle
Semantik!! Das Festlegen konkreter Definitionen führt zwangsläufig dazu, dass einige Antworten und Kommentare nicht kompatibel sind, da sie nicht dasselbe beschreiben, selbst wenn dieselben Wörter und Ausdrücke verwendet werden. Es ist jedoch wichtig, die Verwirrung zu überwinden (insbesondere für neue Programmierer).
Erstens gibt es mehrere Abstraktionsebenen, die nicht jeder zu verstehen scheint. Neuere Programmierer, die Sprachen der 4. oder 5. Generation gelernt haben, haben möglicherweise Schwierigkeiten, sich mit Konzepten zu beschäftigen, die Assembler- oder C-Programmierern vertraut sind, die nicht durch Zeiger auf Zeiger auf Zeiger gestaffelt sind. Referenzübergabe bedeutet nicht einfach die Möglichkeit, ein referenziertes Objekt mithilfe einer Funktionsparametervariablen zu ändern.
Variable : Kombiniertes Konzept eines Symbols, das auf einen Wert an einer bestimmten Stelle im Speicher verweist. Dieser Begriff ist normalerweise zu geladen, um allein zur Erörterung von Details verwendet zu werden.
Symbol : Textzeichenfolge, die auf die Variable verweist (dh den Namen der Variablen).
Wert : Bestimmte Bits, die im Speicher gespeichert sind und mit dem Variablensymbol referenziert werden.
Speicherort : Hier wird der Wert einer Variablen gespeichert. (Der Ort selbst wird durch eine Zahl dargestellt, die von dem am Ort gespeicherten Wert getrennt ist.)
Funktionsparameter : In einer Funktionsdefinition deklarierte Variable, die zum Verweisen auf an die Funktion übergebene Variablen verwendet wird.
Funktionsargument : Variable außerhalb der Funktion, die vom Aufrufer an die Funktion übergeben wird.
Objektvariable : Variable, deren grundlegender Grundwert nicht das "Objekt" selbst ist, sondern deren Wert ein Zeiger (Speicherplatzwert) auf einen anderen Speicherort ist, an dem die tatsächlichen Daten des Objekts gespeichert sind. In den meisten Sprachen der höheren Generation wird der Aspekt "Zeiger" durch automatische De-Referenzierung in verschiedenen Kontexten effektiv verborgen.
Primitive Variable : Variable, deren Wert der tatsächliche Wert ist. Selbst dieses Konzept kann durch Auto-Boxing und objektähnliche Kontexte verschiedener Sprachen kompliziert werden. Die allgemeine Idee ist jedoch, dass der Wert der Variablen der tatsächliche Wert ist, der durch das Symbol der Variablen dargestellt wird, und nicht ein Zeiger auf einen anderen Speicherort.
Funktionsargumente und Parameter sind nicht dasselbe. Außerdem ist der Wert einer Variablen nicht das Objekt der Variablen (wie bereits von verschiedenen Personen hervorgehoben, aber anscheinend ignoriert). Diese Unterscheidungen sind entscheidend für das richtige Verständnis.
Pass-by-Value oder Call-by-Sharing (für Objekte): Der Wert des Funktionsarguments wird auf einen anderen Speicherort kopiert, auf den das Parametersymbol der Funktion verweist (unabhängig davon, ob er sich auf dem Stapel oder auf dem Heap befindet). Mit anderen Worten, der Funktionsparameter hat eine Kopie des Wertes des übergebenen Arguments erhalten ... UND (kritisch) der Wert des Arguments wird von der aufrufenden Funktion NIE AKTUALISIERT / GEÄNDERT / GEÄNDERT. Denken Sie daran, dass der Wert einer Objektvariablen NICHT das Objekt selbst ist, sondern der Zeiger auf das Objekt. Wenn Sie also eine Objektvariable als Wert übergeben, wird der Zeiger auf die Funktionsparametervariable kopiert. Der Wert des Funktionsparameters zeigt auf genau dasselbe Objekt im Speicher. Die Objektdaten selbst können direkt über den Funktionsparameter geändert werden, ABER der Wert des Funktionsarguments wird NIE AKTUALISIERT, sodass er weiterhin auf denselben zeigtObjekt während und sogar nach dem Funktionsaufruf (auch wenn die Daten seines Objekts geändert wurden oder wenn dem Funktionsparameter ein anderes Objekt zugewiesen wurde). Es ist falsch zu schließen, dass das Funktionsargument als Referenz übergeben wurde, nur weil das referenzierte Objekt über die Funktionsparametervariable aktualisiert werden kann.
Aufruf / Referenzübergabe : Der Wert des Funktionsarguments kann / wird direkt durch den entsprechenden Funktionsparameter aktualisiert. Wenn dies hilft, wird der Funktionsparameter zu einem effektiven "Alias" für das Argument - er verweist effektiv auf denselben Wert am selben Speicherort. Wenn ein Funktionsargument eine Objektvariable ist, unterscheidet sich die Möglichkeit, die Daten des Objekts zu ändern, nicht vom Fall der Wertübergabe, da der Funktionsparameter weiterhin auf dasselbe Objekt wie das Argument verweist. Wenn im Fall der Objektvariablen der Funktionsparameter auf ein völlig anderes Objekt gesetzt ist, verweist das Argument ebenfalls auf das andere Objekt - dies geschieht im Fall der Wertübergabe nicht.
JavaScript wird nicht als Referenz übergeben. Wenn Sie genau lesen, werden Sie feststellen, dass alle gegensätzlichen Meinungen falsch verstehen, was unter Übergabe von Werten zu verstehen ist, und fälschlicherweise zu dem Schluss kommen, dass die Möglichkeit, die Daten eines Objekts über den Funktionsparameter zu aktualisieren, gleichbedeutend mit "Übergabe nach Wert" ist.
Objekt klonen / kopieren : Ein neues Objekt wird erstellt und die Daten des ursprünglichen Objekts werden kopiert. Dies kann eine tiefe oder flache Kopie sein, aber der Punkt ist, dass ein neues Objekt erstellt wird. Das Erstellen einer Kopie eines Objekts ist ein vom Wertübergabe getrenntes Konzept. Einige Sprachen unterscheiden zwischen Klassenobjekten und Strukturen (oder dergleichen) und haben möglicherweise ein unterschiedliches Verhalten beim Übergeben von Variablen der verschiedenen Typen. JavaScript führt so etwas jedoch nicht automatisch aus, wenn Objektvariablen übergeben werden. Das Fehlen des automatischen Klonens von Objekten führt jedoch nicht zu einer Referenzübergabe.
quelle
JavaScript übergibt primitive Typen als Wert und Objekttypen als Referenz
- Brian Bi - Welche Programmiersprachen werden als Referenz übergeben?
Aktualisieren
Hier ist eine Gegenargumentation dazu:
In JavaScript ist keine "Referenzübergabe" verfügbar.
quelle
Mein einfacher Weg, das zu verstehen ...
Wenn Sie eine Funktion aufrufen, übergeben Sie den Inhalt (Referenz oder Wert) der Argumentvariablen, nicht die Variablen selbst.
Innerhalb der Funktion erhalten Parametervariablen
inVar1
undinVar2
den Inhalt, der übergeben wird.Seit Sie
inVar2
die Referenz von erhalten haben{ prop: 2 }
, können Sie den Wert der Objekteigenschaft ändern.quelle
Das Übergeben von Argumenten an eine Funktion in JavaScript entspricht dem Übergeben von Parametern als Zeigerwert in C:
quelle
Für Anwälte in Programmiersprachen habe ich die folgenden Abschnitte von ECMAScript 5.1 (das einfacher zu lesen ist als die neueste Ausgabe) durchgesehen und es sogar auf der ECMAScript-Mailingliste angefragt.
TL; DR : Alles wird als Wert übergeben, aber die Eigenschaften von Objekten sind Referenzen, und die Definition von Objekt fehlt im Standard gruselig.
Erstellung von Argumentlisten
In Abschnitt 11.2.4 "Argumentlisten" wird Folgendes zum Erstellen einer Argumentliste beschrieben, die nur aus einem Argument besteht:
In diesem Abschnitt werden auch Fälle aufgeführt, in denen die Argumentliste 0 oder> 1 Argumente enthält.
Somit wird alles als Referenz übergeben.
Zugriff auf Objekteigenschaften
Abschnitt 11.2.1 "Property Accessors"
Somit stehen Eigenschaften von Objekten immer als Referenz zur Verfügung.
Auf Referenz
In Abschnitt 8.7 "Der Referenzspezifikationstyp" wird beschrieben, dass Referenzen keine echten Typen in der Sprache sind. Sie werden nur verwendet, um das Verhalten der Lösch-, Typ- und Zuweisungsoperatoren zu beschreiben.
Definition von "Objekt"
In der Ausgabe 5.1 ist definiert, dass "Ein Objekt eine Sammlung von Eigenschaften ist". Daher können wir schließen, dass der Wert des Objekts die Sammlung ist, aber was der Wert der Sammlung ist, ist in der Spezifikation schlecht definiert und erfordert ein wenig Aufwand, um zu verstehen.
quelle
Die MDN-Dokumente erklären es klar, ohne zu ausführlich zu sein:
Quelle: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description
quelle
Wenn Sie in einer einfachen Sprache eine Variable als Referenz übergeben möchten, müssen Sie bei der Erstellung der Funktion eine bestimmte Syntax verwenden:
Das
&age
ist eine Referenz aufmyAge
, aber wenn Sie den Wert wollen, müssen Sie die Referenz mit konvertieren*age
.Javascript ist eine Hochsprache, die diese Konvertierung für Sie durchführt. Obwohl Objekte als Referenz übergeben werden, konvertiert die Sprache den Referenzparameter in den Wert. Sie müssen weder
&
die Funktionsdefinition verwenden, um sie als Referenz zu übergeben, noch*
den Funktionskörper, um die Referenz in den Wert zu konvertieren. JS erledigt dies für Sie.Wenn Sie versuchen, ein Objekt innerhalb einer Funktion zu ändern, indem Sie dessen Wert (dh
age = {value:5}
) ersetzen , bleibt die Änderung daher nicht bestehen. Wenn Sie jedoch die Eigenschaften (dhage.value = 5
) ändern , ist dies der Fall.Erfahren Sie mehr
quelle
Ich habe diese Antworten mehrmals durchgelesen, aber nicht WIRKLICH verstanden, bis ich von der technischen Definition von "Call by Sharing", wie sie von Barbara Liskov genannt wird, erfahren habe
Das heißt, Parameterreferenzen können geändert werden, wenn Sie auf den Parameterwert selbst zugreifen. Andererseits verschwindet die Zuordnung zu einem Parameter nach der Auswertung und ist für den Funktionsaufrufer nicht zugänglich.
quelle
Meist einfachster Weg
quelle
JSON.parse( JSON.stringify( obj ) )
ist ein schrecklicher Weg, um Objekte tief zu klonen. Es ist nicht nur langsam, sondern kann auch Datenverlust verursachen.Ich habe die Extend-Methode der Underscore.js-Bibliothek als sehr nützlich empfunden , wenn ich ein Objekt als Parameter übergeben möchte, der entweder geändert oder vollständig ersetzt werden kann.
quelle
Die prägnanteste Erklärung, die ich gefunden habe, war im AirBNB-Styleguide :
Grundelemente : Wenn Sie auf einen Grundelementtyp zugreifen, arbeiten Sie direkt an dessen Wert
Z.B:
Komplex : Wenn Sie auf einen komplexen Typ zugreifen, arbeiten Sie an einem Verweis auf dessen Wert
Z.B:
Das heißt, primitive Typen werden effektiv als Wert übergeben, und komplexe Typen werden als Referenz übergeben.
quelle
Ich würde sagen, es ist Pass-by-Copy -
Betrachten Sie Argumente und variable Objekte als Objekte, die während des Ausführungskontexts erstellt wurden, der zu Beginn des Funktionsaufrufs erstellt wurde - und Ihr tatsächlicher Wert / Ihre Referenz, die an die Funktion übergeben werden, werden nur in diesen Argumenten + variablen Objekten gespeichert.
Einfach gesagt, für primitive Typen werden die Werte zu Beginn des Funktionsaufrufs kopiert, für den Objekttyp wird die Referenz kopiert.
quelle
Es gibt einige Diskussionen über die Verwendung des Begriffs „als Verweis übergeben“ in JavaScript hier , aber Ihre Frage zu beantworten:
(Aus dem oben genannten Artikel.)
quelle
Eine einfache Möglichkeit, um festzustellen, ob etwas "Referenzübergabe" ist, besteht darin, ob Sie eine "Swap" -Funktion schreiben können. In C können Sie beispielsweise Folgendes tun:
Wenn Sie dies in JavaScript nicht tun können, handelt es sich nicht um "Referenzübergabe".
quelle
Array und Objekt werden basierend auf diesen beiden Bedingungen als Referenzübergabe oder als Übergabewert übergeben.
Wenn Sie den Wert dieses Objekts oder Arrays durch ein neues Objekt oder Array ändern, wird es als Wert übergeben.
object1 = {item: "car"}; array1=[1,2,3];
Hier weisen Sie dem alten Objekt ein neues Objekt oder Array zu. Sie ändern den Wert der Eigenschaft des alten Objekts nicht. Es wird also als Wert übergeben.
Wenn Sie einen Eigenschaftswert eines Objekts oder Arrays ändern, wird dieser als Referenz übergeben.
object1.key1= "car"; array1[0]=9;
Hier ändern Sie einen Eigenschaftswert des alten Objekts. Sie weisen dem alten Objekt kein neues Objekt oder Array zu. Es wird also als Referenz übergeben.
Code
quelle
quelle
Einfache Werte innerhalb von Funktionen ändern diese Werte außerhalb der Funktion nicht (sie werden als Wert übergeben), während komplexe Werte (sie werden als Referenz übergeben).
quelle