2016-07-21 16 views
11

Ostatnio sprawdzałem słodki kod, aby zamienić dwie zmienne za pomocą funkcji XOR. Do tego użyłem JavaScript.Dlaczego te instrukcje działają inaczej w JavaScript?

Niech x i y będą dwiema zmiennymi i niech x = 4, y = 6.

x = x^y; y = y^x; x = x^y;

To zamienia zmienne ładnie. Zauważ, że zachowuję różne ustawienia x i y, aby zapobiec aliasingowi, który może wystąpić z powodu pierwszego XOR.

Następnie obserwując oświadczenie, napisałem: x = x^(y = y^(x = x^y)); ta zamienia zmienną y poprawnie, ale sprawia x zawsze 0.

Również, x ^= y ^= x ^= y;, który również wydaje się być ekwiwalentnym wyrażeniem, daje taki sam nieprawidłowy wynik jak w drugim przypadku.

Wszystkie te instrukcje działają jednakowo na Javie i konsekwentnie generują ten sam wynik.

Użyłem również trybu ścisłego z JavaScript.

Czy te trzy stwierdzenia nie są w jakiś sposób równoważne w JavaScript lub czy brakuje mi tu czegoś krytycznego?

+3

try 'x = (y = y^(x = x^y))^x;' zamiast tego - przed oceną trzeba było zmienić x Ostatni ostatni nie zadziała, ponieważ pierwsza część 'x^'(znalezienie wartości początkowej) jest wykonywane przed ponownym przypisaniem x. – dandavis

+0

niezależna od typu wymiana bez leksykalnego: 'var x = 4, y = 6; x = [y, y = x] [0]; [x, y] ' – dandavis

+0

@dandavis Twoje rozwiązanie działa jak urok. Dzięki. Znalazłem swój błąd. Głupi ja. Jeszcze raz dziękuję. – Ozil

Odpowiedz

4
x = x^y; 
y = y^x; 
x = x^y; 

To działa, bo to jak

x_1 = x_0^y_0; 
y_1 = y_0^x_1; 
x_2 = x_1^y_1; 

Następnie,

x_final = x_2 = x_1^y_1 = x_0^y_0^y_0^x_1 = x_0^y_0^y_0^x_0^y_0 
     = y_0 
y_final = y_1 = y_0^x_1 = y_0^x_0^y_0 
     = x_0; 

Twój x = x^(y = y^(x = x^y)); jest jak

x_1 = x_0^y_0; 
y_1 = y_0^x_1; 
x_2 = x_0^y_1; 

Następnie

x_final = x_2 = x_0^y_1 = x_0^y_0^x_1 = x_0^y_0^x_0^y_0 
     = 0 
y_final = y_1 = y_0^x_1 = y_0^x_0^y_0 
     = x_0; 

Pozwoliłoby to, gdyby użytkownik użył x = (y = y^(x = x^y))^x;.

Dzieje się tak dlatego, że JS analizuje wyrażenia od lewej do prawej i chce, aby ta wartość była zmieniona, a nie początkowa.

+0

x^(y = y^(x = x^y)); nie jest taki sam jak (y = y^(x = x^y))^x; to wszystko, co chcesz powiedzieć, prawda? – user1589188

+0

@ user1589188 Krótko mówiąc, tak – Oriol