Javascript-Variablenreferenz / Alias

89

Ist es in Javascript möglich, einem lokalen Variablen einen Alias ​​/ Verweis zuzuweisen?

Ich meine etwas C-ähnliches:

function foo() {
  var x = 1;
  var y = &x;
  y++;
  alert(x); // prints 2 
}

= EDIT =

Ist es möglich, in diesem Code Aliasargumente.callee zu verwenden?:

function foo() {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
  arguments.callee.myStaticVar++;
  return arguments.callee.myStaticVar;
}
gpilotino
quelle
5
Einfache Antwort ist nein. Aber ich habe das Gefühl, dass jemand in SO mit einem Hack kommt, um dies zu tun :)
Amarghosh

Antworten:

173

In JavaScript werden primitive Typen wie Ganzzahlen und Zeichenfolgen als Wert übergeben, während Objekte als Referenz übergeben werden. Um dies zu erreichen, müssen Sie ein Objekt verwenden:

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2
Darin Dimitrov
quelle
das war schnell =) Ich möchte einen Alias ​​für argument.callee in meiner Funktion erstellen (nur um zu vermeiden, dass jedes Mal Argumente.callee eingegeben werden). ist das mit dieser Methode möglich? Wenn ich verstehe, kann ich Alias ​​"Argumente", aber ich muss trotzdem "Angerufene" schreiben, nicht wahr?
Gpilotino
9
@Darin: das ist ein bisschen zu einfach. Es ist unveränderlich gegen veränderbare Typen und nicht gegen primitive Typen gegen Objekte. In JavaScript ist alles ein Objekt in irgendeiner Form.
Crescent Fresh
7
In JS wird die Referenz als Wert übergeben. Es gibt einen Unterschied zwischen "Referenzübergabe" und "Referenzübergabe nach Wert". In Javascript wird die Übergabe von Parametern als Referenz nicht unterstützt.
Corneliu
15

Bis zu einem gewissen Grad ist dies möglich. Sie können einen Alias ​​für eine Variable mithilfe von Abschlüssen erstellen:

Function.prototype.toString = function() {
    return this();
}

var x = 1;
var y = function() { return x }
x++;
alert(y); // prints 2, no need for () because of toString redefinition 
user187291
quelle
1
Ich glaube, "alert (y); // druckt 2" sollte sein: "alert (y ()); // druckt 2" Sie müssen die Funktion tatsächlich aufrufen, um das Ergebnis zu erhalten. Schade, da die vorgeschlagene Syntax in bestimmten Situationen hilfreich wäre.
Nathan Labenz
3
Diese toString-Neudefinition gibt es aus einem Grund, also alert(y)ist sie tatsächlich richtig. Obwohl die Neudefinition von Funktionsprototypmethoden ein sehr schlechter Stil ist. Aber hey, es funktioniert!
Metalim
8

Ob Sie einen Alias ​​erstellen können, hängt vom Datentyp ab. Objekte, Arrays und Funktionen werden als Referenz behandelt, und Aliasing ist möglich. Andere Typen sind im Wesentlichen atomar, und die Variable speichert den Wert und nicht einen Verweis auf einen Wert.

argumente.callee ist eine Funktion, daher können Sie einen Verweis darauf haben und das gemeinsam genutzte Objekt ändern.

function foo() {
  var self = arguments.callee;
  self.myStaticVar = self.myStaticVar || 0;
  self.myStaticVar++;
  return self.myStaticVar;
}

Beachten Sie, dass , wenn in dem obigen Code , den Sie sagen , sind self = function() {return 42;};dann selfdann zu einem beziehen würde anderes Objekt als arguments.callee, die ein Bezugspunkt bleibt foo. Wenn Sie ein zusammengesetztes Objekt haben, ersetzt der Zuweisungsoperator die Referenz und ändert das referenzierte Objekt nicht. Mit Ordnungswerte, ein Fall wie y++entspricht y = y + 1, die eine ‚neue‘ Ganzzahl auf die Variable zuweist.

Nur verliebt
quelle
Ganz zu schweigen davon, dass es arguments.calleebereits einen Alias ​​gibt, der der Name der Funktion ist. In diesem Beispiel könnten Sie nur verwenden foo.myStaticVar(vielleicht war dies 2009 nicht der Fall?)
aljgom
1

Bearbeiten Sie meine vorherige Antwort: Wenn Sie die Aufrufe einer Funktion zählen möchten, möchten Sie möglicherweise Folgendes versuchen:

var countMe = ( function() {
  var c = 0;

  return function() {
    c++;
    return c;
  }
})();

alert(countMe()); // Alerts "1"
alert(countMe()); // Alerts "2"

Hier dient c als Zähler, und Sie müssen keine Argumente verwenden.

Tom Bartel
quelle
oder Sie könnten eine statische Variable verwenden countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom
1

Wenn Sie den Beitrag von user187291 erweitern , können Sie auch Getter / Setter verwenden, um die Verwendung von Funktionen zu umgehen .

var x = 1;
var ref = {
    get x()  { return x; },
    set x(v) { x = v; }
};
(ref.x)++;
console.log(x); // prints '2'
x--;
console.log(ref.x); // prints '1'
Steven Jimenez
quelle
0

2019 muss ich minimierte jquery-Plugins schreiben, damit ich auch diesen Alias ​​benötige. Beim Testen dieser und anderer Beispiele aus anderen Quellen habe ich einen Weg gefunden, ohne Kopie im Speicher des gesamten Objekts, aber nur eine Referenz zu erstellen. Ich habe dies bereits mit Firefox getestet und zuvor den Tab-Speicher des Task-Managers auf Firefox beobachtet. Der Code lautet:

var {p: d} ={p: document};
console.log(d.body);
Constantin
quelle
Dies übergibt nichts als Referenz, Sie können das Dokument einfach direkt übergeben (das bereits eine Referenz auf ein Objekt ist und als Wert übergeben wird). Durch die Destrukturierung werden keine Aliase erstellt.
Erinnern Sie sich an Monica