Einführung
In diesem Kapitel erklären wir die Strategie der Parameterübergabe an Funktionen in ECMAScript.
In der Informatik wird diese Strategie im Allgemeinen als „Bewertungsstrategie“ bezeichnet (Anmerkung des Onkels: Einige Leute sagen, dass sie als Bewertungsstrategie übersetzt wird, und andere übersetzen sie als Zuweisungsstrategie. Wenn ich mir den folgenden Inhalt ansehe, denke ich, dass sie so heißt Zuweisungsstrategie ist ohnehin angemessener, der Titel sollte als Bewertungsstrategie geschrieben werden, die für jedermann leicht verständlich ist, beispielsweise das Festlegen von Regeln für die Bewertung oder Berechnung von Ausdrücken in einer Programmiersprache. Die Strategie der Übergabe von Argumenten an Funktionen ist ein Sonderfall.
http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/
Der Grund für das Schreiben dieses Artikels ist, dass jemand im Forum nach einer genauen Erklärung einiger Parameterübergabestrategien gefragt hat. Wir haben hier die entsprechenden Definitionen angegeben und hoffen, dass sie für alle hilfreich sind.
Viele Programmierer sind davon überzeugt, dass in JavaScript (und sogar einigen anderen Sprachen) Objekte als Referenz übergeben werden, während primitive Werttypen als Wert übergeben werden. Darüber hinaus erwähnen viele Artikel diese „Tatsache“, aber viele Leute tun dies wirklich Verstehen Sie diese Terminologie und wie viel ist richtig? Wir werden sie in diesem Artikel einzeln erklären.
Allgemeine Theorie
Es ist zu beachten, dass es in der Zuweisungstheorie im Allgemeinen zwei Zuweisungsstrategien gibt: strikt – das bedeutet, dass die Parameter vor der Eingabe des Programms berechnet werden; ist, äquivalent zu verzögerter Berechnung).
Dann betrachten wir hier die grundlegende Strategie zur Übergabe von Funktionsparametern, die vom ECMAScript-Ausgangspunkt aus sehr wichtig ist. Als Erstes ist zu beachten, dass ECMAScript (und sogar andere Sprachen wie C, JAVA, Python und Ruby) eine strikte Parameterübergabestrategie verwendet.
Darüber hinaus ist auch die Berechnungsreihenfolge der übergebenen Parameter sehr wichtig – in ECMAScript erfolgt sie von links nach rechts, und die in anderen Sprachen implementierte Reflexionsreihenfolge (von rechts) kann ebenfalls verwendet werden.
Die strikte Parameterübergabestrategie ist außerdem in mehrere Unterstrategien unterteilt, von denen wir die wichtigsten in diesem Kapitel ausführlich besprechen.
Nicht alle unten besprochenen Strategien werden in ECMAScript verwendet. Wenn wir also das spezifische Verhalten dieser Strategien diskutieren, verwenden wir Pseudocode, um sie zu demonstrieren.
Wert übergeben
Wertübergabe, wie viele Entwickler sehr gut wissen. Der Wert eines Parameters ist eine Kopie des vom Aufrufer übergebenen Werts des Parameters Parameter ist in Externer Wert), im Allgemeinen wird neuer Speicher neu zugewiesen (wir achten nicht darauf, wie der zugewiesene Speicher implementiert wird - es handelt sich auch um einen Stapel oder eine dynamische Speicherzuweisung), der Wert des neuen Speicherblocks ist eine Kopie davon das externe Objekt und sein Wert wird innerhalb der Funktion verwendet.
Lassen Sie uns ein allgemeines Beispiel geben und die folgende Zuweisungsstrategie verwenden, um es zu testen. Der erste Parameter ist der Wert des Objekts und der zweite Parameter ist eine boolesche Markierung Das Objekt wurde vollständig geändert (dem Objekt wurde ein Wert neu zugewiesen) oder es wurden nur einige Eigenschaften des Objekts geändert.
Übergabe als Referenz
Eine andere bekannte Methode zur Referenzübergabe erhält keine Kopie des Werts, sondern eine implizite Referenz auf das Objekt, beispielsweise die direkte externe Referenzadresse des Objekts. Jede Änderung der Parameter innerhalb der Funktion wirkt sich auf den Wert des Objekts außerhalb der Funktion aus, da sich beide auf dasselbe Objekt beziehen, das heißt: Zu diesem Zeitpunkt entspricht der Parameter einem Alias des externen Objekts.
Pseudocode:
Anrufen durch Teilen
Jeder kennt die beiden oben genannten Strategien, aber die Strategie, über die ich hier sprechen möchte, wird möglicherweise nicht von jedem gut verstanden (eigentlich handelt es sich um eine akademische Strategie). Wir werden jedoch bald sehen, dass genau dies die Strategie ist, bei der es bei Parameterübergabestrategien in ECMAScript eine Schlüsselrolle spielt.
Es gibt auch einige Synonyme für diese Strategie: „Pass by Object“ oder „Pass by Object Sharing“.
Diese Strategie wurde 1974 von Barbara Liskov für die Programmiersprache CLU vorgeschlagen.
Der Kernpunkt dieser Strategie ist: Die Funktion erhält eine Kopie (Kopie) des Objekts, und die Referenzkopie wird mit den formalen Parametern und ihren Werten verknüpft.
Wir können die hier erscheinende Referenz nicht als „Referenz übergeben“ bezeichnen, da der von der Funktion empfangene Parameter kein direkter Objektalias, sondern eine Kopie der Referenzadresse ist.
Der wichtigste Unterschied besteht darin, dass die Neuzuweisung eines neuen Werts zum Parameter innerhalb der Funktion keine Auswirkungen auf das externe Objekt hat (ähnlich wie bei der Referenzübergabe im obigen Beispiel), sondern dass der Parameter eine Adresskopie ist Es kann nicht von außen und von innen auf dasselbe Objekt zugegriffen werden (z. B. ist das externe Objekt keine vollständige Kopie wie bei der Übergabe von Werten), und eine Änderung des Attributwerts des Parameterobjekts wirkt sich auf das externe Objekt aus.
//Verwenden Sie weiterhin diese Objektstruktur
bar = {
x: 10,
Jahr: 20
}
// Die Übergabe des Beitrags wirkt sich auf das Objekt
aus
foo(bar)
// Die Eigenschaften des Objekts wurden geändert
print(bar) // {x: 100, y: 200}
// Neuzuweisung hat keine Auswirkung
foo(bar, true)
// Immer noch der obige Wert
print(bar) // {x: 100, y: 200}
Pass-by-Share ist ein Sonderfall von Pass-by-Value
Die Pass-by-Share-Strategie wird in vielen Sprachen verwendet: Java, ECMAScript, Python, Ruby, Visual Basic usw. Darüber hinaus hat die Python-Community diese Terminologie übernommen, und andere Sprachen können diese Terminologie ebenfalls verwenden, da andere Namen dazu neigen, Verwirrung zu stiften. In den meisten Fällen, etwa in Java, ECMAScript oder Visual Basic, wird diese Strategie auch Pass-by-Value genannt – was bedeutet: spezielle Wertreferenzkopie.
Einerseits ist es so: Der an die Funktion übergebene Parameter ist nur ein Name des gebundenen Werts (Referenzadresse) und hat keinen Einfluss auf das externe Objekt.
Andererseits werden diese Begriffe wirklich als falsch angesehen, ohne näher darauf einzugehen, da in vielen Foren darüber gesprochen wird, wie man Objekte an JavaScript-Funktionen übergibt.
Die allgemeine Theorie besagt zwar, dass er als Wert übergeben wird: Derzeit ist der Wert jedoch das, was wir als Adresskopie (Kopie) bezeichnen, sodass er nicht gegen die Regeln verstößt.
In Ruby wird diese Strategie als Referenzübergabe bezeichnet. Nochmals: Es wird nicht als Kopie der großen Struktur übergeben (d. h. nicht als Wert übergeben), und andererseits haben wir es nicht mit einem Verweis auf das Originalobjekt zu tun und können es daher nicht ändern, dieses Kreuz Das Begriffskonzept kann zu weiteren Problemen führen.
Theoretisch gibt es keinen Sonderfall der Referenzübergabe wie den Sonderfall der Wertübergabe.
Dennoch muss man verstehen, dass bei den oben genannten Technologien (Java, ECMAScript, Python, Ruby usw.) tatsächlich die Strategie „Pass-by-Share“ verwendet wird.
Press Share & Pointer
Für С/С ist diese Strategie ideologisch dieselbe wie die Übergabe eines Zeigers nach einem Wert, jedoch mit einem wichtigen Unterschied: Diese Strategie kann den Zeiger dereferenzieren und das Objekt vollständig mutieren. Im Allgemeinen wird jedoch ein Wertzeiger (Adresszeiger) einem neuen Speicherblock zugewiesen (d. h. der zuvor referenzierte Speicherblock bleibt unverändert); eine Änderung der Objektattribute über den Zeiger wirkt sich auf das externe Adon-Objekt aus.
Also und bei der Zeigerkategorie können wir offensichtlich erkennen, dass diese als Adresswert übergeben wird. In diesem Fall handelt es sich bei Pass-by-Share nur um „syntaktischen Zucker“, der sich wie eine Zeigerzuweisung verhält (aber nicht dereferenzieren kann) oder eine Eigenschaft wie eine Referenz ändert (keine Dereferenzierungsoperation erforderlich). Manchmal kann er auch als „Sichere Zeiger“ bezeichnet werden ".
Allerdings verfügt С/С auch über einen speziellen Syntaxzucker, wenn auf Objekteigenschaften ohne explizite Zeiger-Dereferenzierung verwiesen wird:
ECMAScript-Implementierung
Jetzt kennen wir die Strategie der Übergabe von Objekten als Parameter in ECMAScript – Übergabe durch gemeinsame Nutzung: Das Ändern der Eigenschaften des Parameters wirkt sich auf die Außenseite aus, eine Neuzuweisung hat jedoch keine Auswirkungen auf das externe Objekt. Wie wir oben erwähnt haben, nennen ECMAScript-Entwickler es jedoch im Allgemeinen: Wertübergabe, mit der Ausnahme, dass der Wert eine Kopie der Referenzadresse ist.
JavaScript-Erfinder Brendan Ash schrieb auch: Was übergeben wird, ist eine Kopie der Referenz (Kopie der Adresse). Was also alle im Forum einmal über die Wertübergabe gesagt haben, trifft auch unter dieser Erklärung zu.
Genauer gesagt kann dieses Verhalten als einfache Zuweisung verstanden werden. Wir können sehen, dass sich darin ein völlig anderes Objekt befindet, das sich jedoch auf denselben Wert bezieht – also auf eine Kopie der Adresse.
ECMAScript-Code:
foo-Wert: addr(0xFF) => {x: 100, y: 200} (Adresse 0xFF) <= bar-Wert: addr(0xFF)
Bei der Neuzuweisung erfolgt die Bindung an einen neuen Objektbezeichner (neue Adresse), ohne dass sich dies auf zuvor gebundene Objekte auswirkt:
Wenn wir außerdem nur die vom ECMA-262-Standard bereitgestellte Abstraktionsebene berücksichtigen, sehen wir im Algorithmus nur das Konzept des „Werts“ und den von der Implementierung übergebenen „Wert“ (kann ein primitiver Wert sein). oder ein Objekt), aber gemäß unserer obigen Definition kann es auch als „Wertübergabe“ bezeichnet werden, da die Referenzadresse auch ein Wert ist.
Um jedoch Missverständnisse zu vermeiden (warum die Eigenschaften externer Objekte innerhalb der Funktion geändert werden können), müssen hier noch Details auf Implementierungsebene berücksichtigt werden – was wir als Passing-by-Sharing oder anders betrachten Wörter - Übergeben Sie einen sicheren Zeiger, und es ist für einen sicheren Zeiger unmöglich, das Objekt zu dereferenzieren und zu ändern, aber er kann den Attributwert des Objekts ändern.
Termversion
Lassen Sie uns die Begriffsversion dieser Strategie in ECMAScript definieren.
Man kann es als „Wertübergabe“ bezeichnen – der hier erwähnte Wert ist ein Sonderfall, das heißt, der Wert ist eine Adresskopie. Von dieser Ebene aus können wir sagen: Alle Objekte in ECMAScript mit Ausnahme von Ausnahmen werden als Wert übergeben. Dies ist tatsächlich die abstrakte Ebene von ECMAScript.
Oder in diesem Fall wird es speziell als „Pass-by-Share“ bezeichnet. Daran können Sie den Unterschied zwischen der traditionellen Pass-by-Value und der Pass-by-Reference erkennen. Diese Situation kann in zwei Situationen unterteilt werden: 1: Originalwerte werden als Wert übergeben; 2: Objekte werden durch Teilen übergeben.
Der Satz „Konvertieren eines Objekts in eine Funktion anhand des Referenztyps“ hat nichts mit ECMAScript zu tun und ist falsch.
Fazit
Ich hoffe, dieser Artikel hilft dabei, mehr Details zum Gesamtbild und seiner Implementierung in ECMAScript zu verstehen. Wenn Sie Fragen haben, können Sie diese wie immer gerne besprechen.