referência / alias de variável javascript

89

É possível em javascript atribuir um alias / referência a um var local de alguma forma?

Quero dizer algo como C:

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

= EDITAR =

É possível criar um alias para argumentos.callee neste código ?:

function foo() {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
  arguments.callee.myStaticVar++;
  return arguments.callee.myStaticVar;
}
gpilotino
fonte
5
A resposta simples é não. Mas tenho a sensação de que alguém no SO virá com um hack para fazer isso :)
Amarghosh

Respostas:

173

Em JavaScript, os tipos primitivos, como inteiros e strings, são passados ​​por valor, enquanto os objetos são passados ​​por referência. Portanto, para conseguir isso, você precisa usar um objeto:

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2
Darin Dimitrov
fonte
isso foi rápido =) eu quero fazer um apelido para argumentos.callee dentro da minha função (apenas para evitar digitar argumentos.callee todas as vezes). isso é possível com este método? Se eu entender, posso usar o apelido de "argumentos", mas ainda tenho que escrever "callee" mesmo assim, não é?
gpilotino
9
@Darin: isso é uma simplificação exagerada. São tipos imutáveis ​​vs mutáveis, ao invés de tipos primitivos vs objetos. Em JavaScript, tudo é um objeto de alguma forma.
Crescent Fresh
7
Em JS, a referência é passada por valor. Há uma diferença entre "passar por referência" e "passar uma referência por valor". Em Javascript, a passagem de parâmetros por referência não é suportada.
Corneliu de
15

Até certo ponto, isso é possível, você pode criar um alias para uma variável usando fechamentos:

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
fonte
1
Eu acredito que "alert (y); // imprime 2" deveria ser: "alert (y ()); // imprime 2" Você realmente tem que chamar a função para obter o resultado. Que pena, pois a sintaxe sugerida seria útil em certas situações.
Nathan Labenz
3
Essa redefinição de toString existe por uma razão, então alert(y)está certa. Embora redefinir os métodos de protótipo de Função seja um estilo muito ruim. Mas ei, funciona!
metalim
8

Se você pode criar um alias para algo, depende do tipo de dados. Objetos, matrizes e funções serão tratados por referência e o aliasing é possível. Outros tipos são essencialmente atômicos e a variável armazena o valor em vez de uma referência a um valor.

argumentos.callee é uma função e, portanto, você pode ter uma referência a ela e modificar esse objeto compartilhado.

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

Observe que se no código acima você dissesse, self = function() {return 42;};então selfse referiria a um objeto diferente de arguments.callee, que permanece uma referência ao foo. Quando você tem um objeto composto, o operador de atribuição substitui a referência, ele não altera o objeto referido. Com valores atômicos, um caso como y++é equivalente a y = y + 1, que atribui um 'novo' inteiro à variável.

Apenas apaixonado
fonte
sem falar que arguments.calleejá tem um alias, que é o nome da função. Neste exemplo, você poderia apenas usar foo.myStaticVar(talvez não fosse o caso em 2009?)
aljgom
1

edite a minha resposta anterior: se quiser contar as invocações de uma função, você pode tentar:

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

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

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

Aqui, c serve como contador e você não precisa usar argumentos.callee.

Tom Bartel
fonte
ou você pode usar uma variável estática countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom
1

Expandindo a postagem do user187291 , você também pode usar getters / setters para evitar o uso de funções.

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
fonte
0

em 2019 preciso escrever plugins jquery minificados então preciso também desse alias e então testando esses exemplos e outros, de outras fontes, encontrei um jeito sem copiar na memória do objeto inteiro, mas criando apenas uma referência. Eu testei isso já com o firefox e observando a memória da guia do gerenciador de tarefas no firefox antes. O código é:

var {p: d} ={p: document};
console.log(d.body);
Constantin
fonte
Isso não passa nada por referência, basta passar o documento diretamente (que já é uma referência a um objeto, e é passado por valor). A desestruturação não cria aliases.
Lembre