odniesienie / alias do zmiennej javascript


89

Czy w javascript można jakoś przypisać alias / odwołanie do zmiennej lokalnej?

Mam na myśli coś w stylu C:

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

= EDYCJA =

Czy można w tym kodzie alias arguments.callee ?:

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

5
Prosta odpowiedź brzmi: nie. Ale mam wrażenie, że ktoś z SO przyjdzie z hakiem, aby to zrobić :)
Amarghosh

Odpowiedzi:


173

W JavaScript typy pierwotne, takie jak liczby całkowite i łańcuchy, są przekazywane przez wartość, podczas gdy obiekty są przekazywane przez odwołanie. Aby to osiągnąć, musisz użyć obiektu:

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

to było szybkie =) Chcę utworzyć alias do arguments.callee wewnątrz mojej funkcji (żeby uniknąć wpisywania arguments.callee za każdym razem). czy jest to możliwe w przypadku tej metody? Jeśli rozumiem, mogę pseudonimować „argumenty”, ale i tak muszę napisać „wywoływany”, prawda?
gpilotino

9
@Darin: to jest trochę przesadne uproszczenie. Jest to typ niezmienny i zmienny, a nie typy pierwotne i obiekty. W JavaScript wszystko jest obiektem w jakiejś formie.
Crescent Fresh

7
W JS odwołanie jest przekazywane przez wartość. Istnieje różnica między „przekazywaniem przez odniesienie” a „przekazywaniem-odniesienia-przez-wartość”. W Javascript przekazywanie parametrów przez odniesienie nie jest obsługiwane.
Corneliu,

15

Do pewnego stopnia jest to możliwe, możesz utworzyć alias do zmiennej za pomocą domknięć:

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
Uważam, że "alert (y); // wypisuje 2" powinno być: "alert (y ()); // wypisuje 2" Aby otrzymać wynik, musisz faktycznie wywołać funkcję. Szkoda, ponieważ sugerowana składnia byłaby pomocna w niektórych sytuacjach.
Nathan Labenz

3
To, że ponowna definicja toString istnieje z jakiegoś powodu, więc w alert(y)rzeczywistości ma rację. Chociaż redefiniowanie metod prototypowych funkcji jest bardzo złym stylem. Ale hej, to działa!
metalim

8

To, czy możesz coś aliasować, zależy od typu danych. Obiekty, tablice i funkcje będą obsługiwane przez referencje i możliwe jest tworzenie aliasów. Inne typy są zasadniczo niepodzielne, a zmienna przechowuje wartość, a nie odwołanie do wartości.

arguments.callee jest funkcją, dlatego możesz mieć do niej odniesienie i modyfikować ten obiekt współdzielony.

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

Należy pamiętać, że jeśli w powyższym kodzie byłaś powiedzieć self = function() {return 42;};następnie selfbyłyby następnie odwołać się do innego obiektu niż arguments.callee, który pozostaje odniesienie do foo. W przypadku obiektu złożonego operator przypisania zastępuje odwołanie, nie zmienia natomiast obiektu, do którego się odnosi. W przypadku wartości niepodzielnych przypadek taki jak y++jest równoważny z y = y + 1przypisaniem „nowej” liczby całkowitej do zmiennej.


nie wspominając arguments.calleejuż o tym, że ma już alias, czyli nazwę funkcji. W tym przykładzie możesz po prostu użyć foo.myStaticVar(może nie było to w 2009 roku?)
aljgom

2

Rozwijając post user187291 , możesz również użyć getters / setters, aby obejść konieczność używania funkcji.

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'

1

edytuj moją poprzednią odpowiedź: jeśli chcesz policzyć wywołania funkcji, możesz spróbować:

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

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

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

Tutaj c służy jako licznik i nie musisz używać arguments.callee.


lub możesz użyć zmiennej statycznej countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom

1

w 2019 muszę napisać zminimalizowane wtyczki jquery, więc potrzebuję też tego aliasu i testując te i inne przykłady z innych źródeł znalazłem sposób bez kopiowania w pamięci całego obiektu, ale tworząc tylko referencję. Przetestowałem to już z Firefoxem i oglądałem wcześniej pamięć karty menedżera zadań w Firefoksie. Kod to:

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

To nie przekazuje niczego przez referencję, możesz po prostu przekazać dokument bezpośrednio (który już jest referencją do obiektu i jest przekazywany przez wartość). Destrukturyzacja nie tworzy aliasów.
Pamiętaj o Monice
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.