Können wir eine Referenz einer Variablen übergeben, die als Argument in einer Funktion unveränderlich ist?
Beispiel:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
javascript
user1342369
quelle
quelle
Antworten:
Da JavaScript die Übergabe von Parametern als Referenz nicht unterstützt, müssen Sie die Variable stattdessen zu einem Objekt machen:
var x = {Value: 0}; function a(obj) { obj.Value++; } a(x); document.write(x.Value); //Here i want to have 1 instead of 0
In diesem Fall
x
handelt es sich um eine Referenz auf ein Objekt. Wennx
an die Funktion übergeben wirda
, wird diese Referenz in kopiertobj
. Also,obj
undx
beziehen sich auf das gleiche im Gedächtnis. Das Ändern derValue
Eigenschaft vonobj
wirkt sich auf dieValue
Eigenschaft von ausx
.Javascript übergibt Funktionsparameter immer als Wert. Das ist einfach eine Spezifikation der Sprache. Sie können
x
in einem für beide Funktionen lokalen Bereich erstellen und die Variable überhaupt nicht übergeben.quelle
Diese Frage kann helfen: Wie übergebe ich eine Variable als Referenz in Javascript? Lesen Sie Daten aus der ActiveX-Funktion, die mehr als einen Wert zurückgibt
Zusammenfassend lässt sich sagen, dass primitive Javascript-Typen immer als Wert übergeben werden, während die Werte in Objekten als Referenz übergeben werden (danke an Kommentatoren, die auf mein Versehen hingewiesen haben). Um dies zu umgehen, müssen Sie Ihre Ganzzahl in ein Objekt einfügen:
var myobj = {x:0}; function a(obj) { obj.x++; } a(myobj); alert(myobj.x); // returns 1
quelle
x
Wert übergeben, unabhängig davon, obx
es sich um ein Objekt handelt oder nicht, können Sie es nicht durch einen ganz anderen Wert ersetzen, wie es der Aufrufer sehen wird.Ich habe einen etwas anderen Weg gefunden, Zeiger zu implementieren, der vielleicht allgemeiner und aus C-Sicht leichter zu verstehen ist (und daher besser in das Format des Benutzerbeispiels passt).
In JavaScript sind Array-Variablen wie in C eigentlich nur Zeiger auf das Array, sodass Sie ein Array genauso verwenden können wie das Deklarieren eines Zeigers. Auf diese Weise können alle Zeiger in Ihrem Code auf dieselbe Weise verwendet werden, obwohl Sie die Variable im ursprünglichen Objekt benannt haben.
Es erlaubt auch, zwei verschiedene Notationen zu verwenden, die sich auf die Adresse des Zeigers und die Adresse des Zeigers beziehen.
Hier ist ein Beispiel (ich benutze den Unterstrich, um einen Zeiger zu bezeichnen):
var _x = [ 10 ]; function foo(_a){ _a[0] += 10; } foo(_x); console.log(_x[0]);
Erträge
output: 20
quelle
Sie verweisen auf 'x' aus dem Fensterobjekt
var x = 0; function a(key, ref) { ref = ref || window; // object reference - default window ref[key]++; } a('x'); // string alert(x);
quelle
Späte Antwort, aber ich bin auf eine Möglichkeit gestoßen, primitive Werte durch Verweise durch Verschlüsse zu übergeben. Es ist ziemlich kompliziert, einen Zeiger zu erstellen, aber es funktioniert.
function ptr(get, set) { return { get: get, set: set }; } function helloWorld(namePtr) { console.log(namePtr.get()); namePtr.set('jack'); console.log(namePtr.get()) } var myName = 'joe'; var myNamePtr = ptr( function () { return myName; }, function (value) { myName = value; } ); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
In ES6 kann der Code gekürzt werden, um Lambda-Ausdrücke zu verwenden:
var myName = 'joe'; var myNamePtr = ptr(=> myName, v => myName = v); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
quelle
In JavaScript wäre das ein globaler. Ihre Funktion würde jedoch eher so aussehen:
function a(){ x++; };
Da
x
es sich um einen globalen Kontext handelt, müssen Sie ihn nicht an die Funktion übergeben.quelle
Javascript sollte nur Zeiger in die Mischung einfügen, da es viele Probleme löst. Dies bedeutet, dass Code auf einen unbekannten Variablennamen oder auf Variablen verweisen kann, die dynamisch erstellt wurden. Es macht auch die modulare Codierung und Injektion einfach.
Dies ist das, was ich als das Beste sehe, was man in der Praxis an c Zeigern erreichen kann
in js:
var a = 78; // creates a var with integer value of 78 var pointer = 'a' // note it is a string representation of the var name eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12
in c:
int a = 78; // creates a var with integer value of 78 int pointer = &a; // makes pointer to refer to the same address mem as a *pointer = 12; // changes the value of a to 12
quelle
Es ist möglicherweise unmöglich, da JavaScript nicht über den Perl-Operator "\" verfügt, um ein Grundelement als Referenz abzurufen. Es gibt jedoch eine Möglichkeit, mithilfe dieses Musters ein "effektiv ein Zeiger" -Objekt für ein Grundelement zu erstellen.
Diese Lösung ist am sinnvollsten, wenn Sie das Grundelement bereits haben (Sie können es also nicht mehr in ein Objekt einfügen, ohne anderen Code ändern zu müssen), aber dennoch einen Zeiger darauf übergeben müssen, damit andere Teile Ihres Codes basteln können mit seinem Zustand; Sie können also weiterhin mit dem nahtlosen Proxy, der sich wie ein Zeiger verhält, an seinem Status basteln.
var proxyContainer = {}; // | attaches a pointer-lookalike getter/setter pair // | to the container object. var connect = function(container) { // | primitive, can't create a reference to it anymore var cant_touch_this = 1337; // | we know where to bind our accessor/mutator // | so we can bind the pair to effectively behave // | like a pointer in most common use cases. Object.defineProperty(container, 'cant_touch_this', { 'get': function() { return cant_touch_this; }, 'set': function(val) { cant_touch_this = val; } }); }; // | not quite direct, but still "touchable" var f = function(x) { x.cant_touch_this += 1; }; connect(proxyContainer); // | looks like we're just getting cant_touch_this // | but we're actually calling the accessor. console.log(proxyContainer.cant_touch_this); // | looks like we're touching cant_touch_this // | but we're actually calling the mutator. proxyContainer.cant_touch_this = 90; // | looks like we touched cant_touch_this // | but we actually called a mutator which touched it for us. console.log(proxyContainer.cant_touch_this); f(proxyContainer); // | we kinda did it! :) console.log(proxyContainer.cant_touch_this);
quelle
In JavaScript können Sie keine Variablen als Referenz auf eine Funktion übergeben. Sie können ein Objekt jedoch als Referenz übergeben.
quelle
Ich denke, dass im Gegensatz zu C oder einer Sprache mit Zeigern:
/** Javascript **/ var o = {x:10,y:20}; var o2 = {z:50,w:200};
.
o == o2 // obviously false : not the same address in memory o <= o2 // true ! o >= o2 // also true !!
Das ist ein großes Problem:
Dies bedeutet, dass Sie alle von Ihrer Anwendung erstellten (zugewiesenen) Objekte auflisten / verwalten können.
Berechnen Sie aus dieser riesigen Liste von Objekten einige Informationen über diese (wie sie zum Beispiel miteinander verknüpft sind).
Wenn Sie jedoch die Informationen abrufen möchten, die Sie über ein bestimmtes Objekt erstellt haben, können Sie diese nicht durch Dichotomie in Ihrer großen Liste finden : Es gibt keine eindeutige Kennung pro Objekt , die als Ersatz für die reale Speicheradresse verwendet werden könnte
Dies bedeutet schließlich, dass dies ein großes Problem ist, wenn Sie in Javascript schreiben möchten:
quelle
JavaScript unterstützt nicht die Übergabe primitiver Typen als Referenz. Es gibt jedoch eine Problemumgehung.
Fügen Sie alle Variablen, die Sie übergeben müssen, in ein Objekt ein. In diesem Fall gibt es nur eine Variable
x
. Anstatt die Variable zu übergeben, übergeben Sie den Variablennamen als Zeichenfolge"x"
.var variables = {x:0}; function a(x) { variables[x]++; } a("x"); alert(variables.x);
quelle
Je nachdem, was Sie tun möchten, können Sie den Variablennamen einfach speichern und später wie folgt darauf zugreifen:
function toAccessMyVariable(variableName){ alert(window[variableName]); } var myFavoriteNumber = 6; toAccessMyVariable("myFavoriteNumber");
Um sich auf Ihr spezielles Beispiel zu beziehen, können Sie Folgendes tun:
var x = 0; var pointerToX = "x"; function a(variableName) { window[variableName]++; } a(pointerToX); alert(x); //Here I want to have 1 instead of 0
quelle
window
objektspezifisch. Es wird auch weniger empfohlen, globale Variablen zu verwenden, da möglicherweise bereits eine Variable mit demselben Namen vorhanden ist.Es unterstützt nur keine Zeiger, Ende der Geschichte :-(.
Ich möchte hinzufügen, dass Sie, obwohl ich brandneu bin und einen C-Hintergrund habe, nach dem, was ich über die Ereignisschleife und den Stapel lese, jedes Objekt so nah wie möglich an seinem Aufrufer halten sollten. Da ich brandneu bin, könnte ich das falsch machen.
Viele Antworten hier schlagen vor, es global zu machen, aber wenn ich richtig lese, könnte dies möglicherweise die Stapelsprünge erhöhen und in gewisser Weise Ihre Ereignisschleife unnötig fragmentieren (abhängig davon, was das aufgerufene Objekt gerade tut).
Außerdem ist jedes Beispiel, das Zeiger nachahmt, in vielerlei Hinsicht nur 1, um dasselbe zu tun, was kein Zeiger sein wird.
quelle
Nein, du kannst nicht. Der Browser gewährt Ihnen keinen Zugriff auf den Systemspeicher und seine Variablen. Es sollte mit einer Umgebung wie einem Knoten möglich sein, aber im Browser ist dies nur möglich, wenn Sie ein Hacker sind.
quelle
In Ihrem Beispiel haben Sie tatsächlich 2 Variablen mit demselben Namen. Die (globale) Variable x und die Variable x mit Funktionsbereich . Es ist interessant zu sehen, dass Javascript, wenn es die Wahl hat, was mit zwei gleichnamigen Variablen zu tun ist, zum Funktionsbereichsnamen passt und die Variable außerhalb des Gültigkeitsbereichs ignoriert.
Es ist wahrscheinlich nicht sicher anzunehmen, dass sich Javascript immer so verhält ...
Prost!
quelle
var x = 0; Funktion a () {x ++; } a (x); console.log (x);
quelle