référence / alias de variable javascript

89

Est-il possible en javascript d'attribuer un alias / une référence à une variable locale?

Je veux dire quelque chose du genre C:

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

= MODIFIER =

Est-il possible d'aliaser arguments.callee dans ce code?:

function foo() {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
  arguments.callee.myStaticVar++;
  return arguments.callee.myStaticVar;
}
gpilotino
la source
5
La réponse simple est non. Mais j'ai le sentiment que quelqu'un dans SO viendra avec un hack pour faire ça :)
Amarghosh

Réponses:

173

En JavaScript, les types primitifs tels que les entiers et les chaînes sont passés par valeur tandis que les objets sont passés par référence. Donc, pour y parvenir, vous devez utiliser un objet:

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2
Darin Dimitrov
la source
c'était rapide =) je veux créer un alias pour arguments.callee dans ma fonction (juste pour éviter de taper arguments.callee à chaque fois). est-ce possible avec cette méthode? Si je comprends, je peux alias "arguments" mais je dois quand même écrire "callee", n'est-ce pas?
gpilotino
9
@Darin: c'est un peu simplifier. Il s'agit de types immuables vs mutables, plutôt que de types primitifs vs objets. En JavaScript, tout est un objet sous une forme ou une autre.
Crescent Fresh
7
Dans JS, la référence est passée par valeur. Il existe une différence entre «passer par référence» et «passer une référence par valeur». En Javascript, le passage des paramètres par référence n'est pas pris en charge.
Corneliu
15

Dans une certaine mesure, cela est possible, vous pouvez créer un alias vers une variable à l'aide de fermetures:

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
la source
1
Je crois que "alert (y); // imprime 2" devrait être: "alert (y ()); // imprime 2" Vous devez réellement appeler la fonction pour obtenir le résultat. Dommage, car la syntaxe suggérée serait utile dans certaines situations.
Nathan Labenz
3
Cette redéfinition de toString est là pour une raison, elle a donc alert(y)raison. Bien que redéfinir les méthodes des prototypes de fonction soit un très mauvais style. Mais bon, ça marche!
metalim
8

La possibilité de créer un alias dépend du type de données. Les objets, tableaux et fonctions seront gérés par référence et l'alias est possible. Les autres types sont essentiellement atomiques et la variable stocke la valeur plutôt qu'une référence à une valeur.

arguments.callee est une fonction, et vous pouvez donc y faire référence et modifier cet objet partagé.

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

Notez que si dans le code ci-dessus vous deviez dire, self = function() {return 42;};alors selfferait référence à un objet différent de arguments.callee, qui reste une référence à foo. Lorsque vous avez un objet composé, l'opérateur d'affectation remplace la référence, il ne modifie pas l'objet référencé. Avec les valeurs atomiques, un cas comme y++est équivalent à y = y + 1, qui assigne un «nouvel» entier à la variable.

Juste amoureux
la source
sans oublier qu'il a arguments.calleedéjà un alias, qui est le nom de la fonction. Dans cet exemple, vous pouvez simplement utiliser foo.myStaticVar(peut-être que ce n'était pas le cas en 2009?)
aljgom
1

modifier à ma réponse précédente: si vous souhaitez compter les appels d'une fonction, vous pouvez essayer:

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

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

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

Ici, c sert de compteur, et vous n'avez pas besoin d'utiliser arguments.callee.

Tom Bartel
la source
ou vous pouvez utiliser une variable statique countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom
1

En développant le message de user187291 , vous pouvez également utiliser des getters / setters pour éviter d'utiliser des fonctions.

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
la source
0

en 2019, j'ai besoin d'écrire des plugins jquery minifiés, donc j'en ai besoin aussi cet alias et donc en testant ces exemples et d'autres, à partir d'autres sources, j'ai trouvé un moyen sans copie dans la mémoire de l'objet entier, mais en ne créant qu'une référence. J'ai déjà testé cela avec Firefox et en regardant la mémoire des onglets du gestionnaire de tâches sur Firefox avant. Le code est:

var {p: d} ={p: document};
console.log(d.body);
Constantin
la source
Cela ne passe rien par référence, vous pouvez simplement passer le document directement (qui est déjà une référence à un objet, et est passé par valeur). La déstructuration ne crée pas d'alias.
Souvenez