Czy możemy przekazać referencję do zmiennej, która jest niezmienna jako argument w funkcji?
Przykład:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
javascript
user1342369
źródło
źródło
Odpowiedzi:
Ponieważ JavaScript nie obsługuje przekazywania parametrów przez odniesienie, musisz zamiast tego uczynić zmienną obiektem:
var x = {Value: 0}; function a(obj) { obj.Value++; } a(x); document.write(x.Value); //Here i want to have 1 instead of 0
W tym przypadku
x
jest to odniesienie do obiektu. Kiedyx
jest przekazywane do funkcjia
, to odwołanie jest kopiowane doobj
. Tak więcobj
ix
odnoszą się do tego samego w pamięci. ZmianaValue
właściwościobj
wpływa naValue
właściwośćx
.JavaScript zawsze przekazuje parametry funkcji według wartości. To po prostu specyfikacja języka. Państwo mogłoby stworzyć
x
w zakresie lokalnego do obu funkcji, a nie przekazać zmienną w ogóle.źródło
To pytanie może pomóc: jak przekazać zmienną przez odniesienie w javascript? Odczytaj dane z funkcji ActiveX, która zwraca więcej niż jedną wartość
Podsumowując, typy pierwotne Javascript są zawsze przekazywane przez wartość, podczas gdy wartości wewnątrz obiektów są przekazywane przez referencje (dzięki komentatorom za zwrócenie uwagi). Aby to obejść, musisz umieścić swoją liczbę całkowitą wewnątrz obiektu:
var myobj = {x:0}; function a(obj) { obj.x++; } a(myobj); alert(myobj.x); // returns 1
źródło
x
wartość, niezależnie od tego, czyx
jest to obiekt, czy nie, nie możesz zastąpić jej całą inną wartością w żaden sposób, który wywołujący zobaczy.Znalazłem nieco inny sposób implementacji wskaźników, który jest być może bardziej ogólny i łatwiejszy do zrozumienia z perspektywy C (a zatem bardziej pasuje do formatu przykładu użytkownika).
W JavaScript, podobnie jak w C, zmienne tablicowe są w rzeczywistości tylko wskaźnikami do tablicy, więc możesz użyć tablicy tak samo, jak zadeklarowanie wskaźnika. W ten sposób wszystkie wskaźniki w kodzie mogą być używane w ten sam sposób, pomimo tego, jak nazwaliście zmienną w oryginalnym obiekcie.
Pozwala również na użycie dwóch różnych notacji odnoszących się do adresu wskaźnika i tego, co znajduje się pod adresem wskaźnika.
Oto przykład (podkreślenia używam do oznaczenia wskaźnika):
var _x = [ 10 ]; function foo(_a){ _a[0] += 10; } foo(_x); console.log(_x[0]);
Plony
output: 20
źródło
Odwołujesz się do „x” z obiektu okna
var x = 0; function a(key, ref) { ref = ref || window; // object reference - default window ref[key]++; } a('x'); // string alert(x);
źródło
Późna odpowiedź, ale natknąłem się na sposób przekazywania prymitywnych wartości przez odniesienie za pomocą domknięć. Utworzenie wskaźnika jest dość skomplikowane, ale działa.
function ptr(get, set) { return { get: get, set: set }; } function helloWorld(namePtr) { console.log(namePtr.get()); namePtr.set('jack'); console.log(namePtr.get()) } var myName = 'joe'; var myNamePtr = ptr( function () { return myName; }, function (value) { myName = value; } ); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
W ES6 kod można skrócić do użycia wyrażeń lambda:
var myName = 'joe'; var myNamePtr = ptr(=> myName, v => myName = v); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
źródło
W JavaScript byłoby to globalne. Jednak twoja funkcja wyglądałaby bardziej tak:
function a(){ x++; };
Ponieważ
x
jest w kontekście globalnym, nie musisz przekazywać go do funkcji.źródło
JavaScript powinien po prostu wstawiać wskaźniki do miksu, ponieważ rozwiązuje wiele problemów. Oznacza to, że kod może odnosić się do nieznanej nazwy zmiennej lub zmiennych, które zostały utworzone dynamicznie. Ułatwia również modułowe kodowanie i wstrzykiwanie.
Oto, co uważam za najbliższe wskazówki, jakie można osiągnąć w praktyce
w js:
var a = 78; // creates a var with integer value of 78 var pointer = 'a' // note it is a string representation of the var name eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12
w c:
int a = 78; // creates a var with integer value of 78 int pointer = &a; // makes pointer to refer to the same address mem as a *pointer = 12; // changes the value of a to 12
źródło
Może to być niemożliwe, ponieważ JavaScript nie ma operatora „\” Perla, aby uzyskać prymityw przez odniesienie, ale istnieje sposób na utworzenie obiektu „efektywnego wskaźnika” dla prymitywu przy użyciu tego wzorca.
To rozwiązanie jest najbardziej sensowne, gdy masz już prymityw (więc nie możesz już umieścić go w obiekcie bez konieczności modyfikowania innego kodu), ale nadal musisz przekazać do niego wskaźnik, aby inne części kodu majstrowały ze swoim stanem; więc nadal możesz majstrować przy jego stanie za pomocą płynnego proxy, które zachowuje się jak wskaźnik.
var proxyContainer = {}; // | attaches a pointer-lookalike getter/setter pair // | to the container object. var connect = function(container) { // | primitive, can't create a reference to it anymore var cant_touch_this = 1337; // | we know where to bind our accessor/mutator // | so we can bind the pair to effectively behave // | like a pointer in most common use cases. Object.defineProperty(container, 'cant_touch_this', { 'get': function() { return cant_touch_this; }, 'set': function(val) { cant_touch_this = val; } }); }; // | not quite direct, but still "touchable" var f = function(x) { x.cant_touch_this += 1; }; connect(proxyContainer); // | looks like we're just getting cant_touch_this // | but we're actually calling the accessor. console.log(proxyContainer.cant_touch_this); // | looks like we're touching cant_touch_this // | but we're actually calling the mutator. proxyContainer.cant_touch_this = 90; // | looks like we touched cant_touch_this // | but we actually called a mutator which touched it for us. console.log(proxyContainer.cant_touch_this); f(proxyContainer); // | we kinda did it! :) console.log(proxyContainer.cant_touch_this);
źródło
W JavaScript nie można przekazywać zmiennych przez odwołanie do funkcji. Możesz jednak przekazać obiekt przez odniesienie.
źródło
Myślę, że w przeciwieństwie do C lub dowolnego języka ze wskazówkami:
/** Javascript **/ var o = {x:10,y:20}; var o2 = {z:50,w:200};
.
o == o2 // obviously false : not the same address in memory o <= o2 // true ! o >= o2 // also true !!
to ogromny problem:
oznacza to, że możesz wyświetlić / zarządzać wszystkimi obiektami utworzonymi (zaalokowanymi) przez Twoją aplikację,
z tej ogromnej listy obiektów obliczyć trochę informacji o nich (na przykład jak są ze sobą połączone)
ale kiedy chcesz pobrać informacje, które utworzyłeś o określonym obiekcie, nie możesz ich znaleźć w swoim ogromnej liście przez dychotomię: nie ma unikalnego identyfikatora dla obiektu, który mógłby zostać użyty jako zamiennik prawdziwego adresu pamięci
to w końcu oznacza, że jest to ogromny problem, jeśli chcesz pisać w javascript:
źródło
JavaScript nie obsługuje przekazywania typów pierwotnych przez odwołanie. Istnieje jednak obejście tego problemu.
Umieść wszystkie zmienne, które musisz przekazać w obiekcie. W tym przypadku istnieje tylko jedna zmienna
x
. Zamiast przekazywać zmienną, przekaż nazwę zmiennej jako ciąg, którym jest"x"
.var variables = {x:0}; function a(x) { variables[x]++; } a("x"); alert(variables.x);
źródło
W zależności od tego, co chcesz zrobić, możesz po prostu zapisać nazwę zmiennej, a następnie uzyskać do niej dostęp później:
function toAccessMyVariable(variableName){ alert(window[variableName]); } var myFavoriteNumber = 6; toAccessMyVariable("myFavoriteNumber");
Aby zastosować się do konkretnego przykładu, możesz zrobić coś takiego:
var x = 0; var pointerToX = "x"; function a(variableName) { window[variableName]++; } a(pointerToX); alert(x); //Here I want to have 1 instead of 0
źródło
window
obiektu. Ponadto stosowanie zmiennych globalnych jest mniej zalecane, ponieważ może już istnieć zmienna o tej samej nazwie.Po prostu nie obsługuje wskaźników, koniec historii :-(.
Chciałbym dodać, że chociaż jestem zupełnie nowy i pochodzę z tła C, z tego, co czytam o pętli zdarzeń i stosie, powinieneś trzymać dowolny obiekt jak najbliżej wywołującego. Ponieważ jestem nowy, mogłem się pomylić.
Wiele odpowiedzi sugeruje, aby uczynić go globalnym, ale ponownie, jeśli dobrze czytam, może to zwiększyć liczbę skoków stosu i w pewnym sensie niepotrzebnie pofragmentować pętlę zdarzeń (w zależności od tego, co aktualnie robi wywołany obiekt).
Ponadto każdy przykład, który naśladuje wskaźniki, jest tylko 1 na wiele sposobów, aby zrobić to samo, co nie będzie wskaźnikiem.
źródło
W twoim przykładzie faktycznie masz 2 zmienne o tej samej nazwie. (Globalna) zmienna x i zakres funkcji x. Ciekawe, że javascript, gdy ma możliwość wyboru, co zrobić z 2 zmiennymi o tej samej nazwie, idzie z nazwą o zakresie funkcji i ignoruje zmienną spoza zakresu.
Prawdopodobnie nie jest bezpiecznie zakładać, że javascript zawsze będzie się zachowywał w ten sposób ...
Twoje zdrowie!
źródło
Nie, nie możesz. Przeglądarka nie daje dostępu do pamięci systemowej i jej zmiennych. Powinno to być możliwe w środowisku takim jak węzeł, ale wewnątrz przeglądarki nie jest to całkiem możliwe, chyba że jesteś hakerem.
źródło