riferimento / alias variabile javascript


89

È possibile in javascript assegnare in qualche modo un alias / riferimento a una variabile locale?

Intendo qualcosa di tipo C:

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

= MODIFICA =

È possibile alias arguments.callee in questo codice ?:

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

5
La semplice risposta è no. Ma ho la sensazione che qualcuno in SO arriverà con un hack per farlo :)
Amarghosh

Risposte:


173

In JavaScript, i tipi primitivi come interi e stringhe vengono passati per valore mentre gli oggetti vengono passati per riferimento. Quindi per ottenere ciò è necessario utilizzare un oggetto:

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2

che era veloce =) voglio creare un alias per arguments.callee all'interno della mia funzione (solo per evitare di digitare arguments.callee ogni volta). è possibile con questo metodo? Se capisco, posso alias "argomenti" ma devo comunque scrivere "callee", non è vero?
gpilotino

9
@Darin: questo semplifica un po 'troppo. È immutabile rispetto a tipi mutabili, piuttosto che tipi primitivi contro oggetti. In JavaScript tutto è un oggetto in qualche forma.
Crescent Fresh

7
In JS il riferimento viene passato per valore. Esiste una differenza tra "passaggio per riferimento" e "passaggio di un riferimento per valore". In Javascript il passaggio di parametri per riferimento non è supportato.
Corneliu

15

In una certa misura questo è possibile, puoi creare un alias per una variabile usando le chiusure:

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 

1
Credo che "alert (y); // stampa 2" dovrebbe essere: "alert (y ()); // stampa 2" Devi effettivamente chiamare la funzione per ottenere il risultato. Peccato, poiché la sintassi suggerita sarebbe utile in determinate situazioni.
Nathan Labenz

3
Quella ridefinizione di toString è lì per una ragione, quindi alert(y)è effettivamente giusta. Sebbene la ridefinizione dei metodi del prototipo di funzione sia uno stile molto negativo. Ma ehi, funziona!
metalim

8

La possibilità di creare un alias dipende dal tipo di dati. Oggetti, array e funzioni verranno gestiti per riferimento ed è possibile creare alias. Altri tipi sono essenzialmente atomici e la variabile memorizza il valore piuttosto che un riferimento a un valore.

arguments.callee è una funzione, quindi puoi avere un riferimento ad essa e modificare quell'oggetto condiviso.

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

Nota che se nel codice sopra dovessi dire, self = function() {return 42;};allora selffarebbe riferimento a un oggetto diverso da arguments.callee, che rimane un riferimento a foo. Quando si dispone di un oggetto composto, l'operatore di assegnazione sostituisce il riferimento, non cambia l'oggetto di riferimento. Con valori atomici, un caso simile y++è equivalente a y = y + 1, che assegna un "nuovo" intero alla variabile.


senza contare che arguments.calleeha già un alias, che è il nome della funzione. In questo esempio potresti semplicemente usare foo.myStaticVar(forse non era così nel 2009?)
aljgom

1

modifica alla mia risposta precedente: se vuoi contare le invocazioni di una funzione, potresti provare:

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

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

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

Qui, c funge da contatore e non è necessario utilizzare arguments.callee.


oppure potresti usare una variabile statica countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom

1

Espandendo il post di user187291 , potresti anche usare getter / setters per aggirare il fatto di dover usare le funzioni.

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'

0

nel 2019 ho bisogno di scrivere plugin jquery minificati quindi ho bisogno anche di questo alias e quindi testando questi esempi e altri, da altre fonti, ho trovato un modo senza copia nella memoria dell'intero oggetto, ma creando solo un riferimento. L'ho già testato con Firefox e guardando la memoria della scheda di Task Manager su Firefox prima. Il codice è:

var {p: d} ={p: document};
console.log(d.body);

Questo non passa nulla per riferimento, puoi semplicemente passare il documento direttamente (che è già un riferimento a un oggetto e viene passato per valore). La destrutturazione non crea alias.
Ricorda Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.