Autor | Zpráva | ||
---|---|---|---|
1Pupik1989 Profil |
#1 · Zasláno: 19. 10. 2014, 22:34:38
Je to spíše pro zajímavost.
Nicméně neví někdo proč následující kód vypíše nesmysl? var x = 80; var y = 50; x ^= y ^= x ^= y; console.log(x,y); // 0, 50 Je to zkráceno z: x ^= y; y ^= x; x ^= y; Přičemž třeba v PHP vypíšou oba příklady správně to samé. Neví někdo v čem je háček? Nemá javascript limit přiřazování na jeden příkaz? |
||
Chamurappi Profil |
Reaguji na 1Pupika1989:
Háček je v interpretaci operátorů, přesněji v pořadí, v jakém se vyhodnocují operandy. Složené přiřazení je v JS (a tuším i v C# a v Javě) brané jen jako zkratka, x ^= y dopadne vždy přesně stejně jako x = x ^ y . Oproti tomu v PHP je nejspíš (stejně jako v C++) speciálním operátorem a je vyhodnocován víc doslovně (víc jako přiřazení). U operátorů v JS je vyhodnocený nejprve levý operand a pak pravý. I kdyby pravý operand provedl nějaké změny proměnné, která se využívá v levém operandu, tak se tato změna na získané hodnotě neprojeví. Naproti tomu v C++ se provádí složené přiřazení úpravu přímo na místě v paměti (nebo referenci objektu před rovnítkem), takže se v podstatě hodnota pravého operandu vyhodnotí dříve.
Tvůj příklad se tedy v JavaScriptu vyhodnocuje takto: x ^= y ^= x ^= y; x = x ^ (y = y ^ (x = x ^ y)); x = 80 ^ (y = y ^ (x = x ^ y)); x = 80 ^ (y = 50 ^ (x = x ^ y)); x = 80 ^ (y = 50 ^ (x = 80 ^ y)); x = 80 ^ (y = 50 ^ (x = 80 ^ 50)); // x = 80, y = 50 x = 80 ^ (y = 50 ^ 98); // x = 98, y = 50 x = 80 ^ 80; // x = 98, y = 80 0; // x = 0, y = 80 Kdežto v C++ (a tedy asi i v PHP) se vyhodnocuje takto: x ^= y ^= x ^= y; x ^= (y ^= (x ^= y)); x ^= (y ^= (x ^= 50)); // x = 80, y = 50 x ^= (y ^= 98); // x = 98, y = 50 x ^= 80; // x = 98, y = 80 50; // x = 50, y = 80 Edit v reakci na _es níže: opraveno, díky za upozornění. |
||
_es Profil |
#3 · Zasláno: 20. 10. 2014, 01:53:27
Chamurappi [#2]:
V 3. riadku prvého kódu je asi chybička (nie 50 ale 80 ).
„ x ^= y dopadne vždy přesně stejně jako x = x ^ y .“
Neplatí to v oboch prípadoch? Príkazy x = x ^ (y = y ^ (x = x ^ y)); , x ^= (y ^= (x ^= y)); a x ^= y ^= x ^= y; sú ekvivalentné, len dajú v rôznych programovacích jazykoch odlišný výsledok.
|
||
1Pupik1989 Profil |
#4 · Zasláno: 20. 10. 2014, 06:59:31
Podle tedy v C++ a PHP se to vyhodnocuje podle mého předpokladu. Nejdřív výpočet a pak přiřazení a počítat od nejhlubšího potomka ve stromu. Čili v tom příkladu zprava doleva.
Co syntaktická analýza, to unikát koukám. |
||
_es Profil |
1Pupik1989:
„Co syntaktická analýza, to unikát koukám.“ Syntaktická analýza je v oboch prípadoch rovnaká, len je rozdiel v tom, čo vysvetlil Chamurappi v [#2] o uchovávaní hodnôt operandov. Je to podobné, ako keď kód v JS var x = 1; alert(x + (x += 1)); 3 , no rovnaká situácia v PHP
$x = 1; echo ($x + ($x += 1)); 4 .
No $x = 1; echo (($x + 0) + ($x += 1)); |
||
1Pupik1989 Profil |
#6 · Zasláno: 20. 10. 2014, 18:01:16
Píšu ze srandy překladač a po přeložení mi správně prohodil hodnoty. Kdežto JS ne. Tak jsem se nad tím pozastavil.
Děkuji za vysvětlení, alespoň vím na co si dát pozor. |
||
Davex Profil |
#7 · Zasláno: 20. 10. 2014, 20:06:00
Kontrolní otázka:
Jak dopadne vyhodnocení těchto výrazů? a = a + b - (b = a); a = a - (b = a) + b; a = b - (b = a) + a; |
||
1Pupik1989 Profil |
#8 · Zasláno: 20. 10. 2014, 21:27:18
Davex: Skončí to "ReferenceError".
Nicméně základem je, že se závorka vykoná nejdříve, na to asi javascript letmo zanevřel. Samý příklad jak jsem psal. Nejdřív je potřeba udělat první přiřazení v řadě, čili poslední a jet doleva. Je docela na prd, že každý překladač na to přistupuje jinak. |
||
Časová prodleva: 10 let
|
0