2010-02-14 15 views
6

W tej chwili uczę się o egzamin na JavaScript. Mam również małą wiedzę na temat C i Perla, więc dobrze znam notację przedrostkową i postfiksową we wszystkich trzech językach.Dlaczego notacja Postfiks JavaScript różni się od C i Perla?

zrobiłem egzaminu online praktyka dla niej i jeden błąd zrobiłem było w ocenie następujący kod:

var x = 10; 
x += x--; 

Teraz, pomyślałem, że to ocenić na 19, ponieważ byłoby to 10 + 10, a następnie odjąć 1 do 9. Ale moja opinia była taka, że ​​była błędna i rzeczywiście wynosi 20. Myślałem, że to brzmi trochę podejrzanie, przetestowałem to w dokumencie HTML, i wyszło z 20 ponownie. Następnie wypróbowałem ekwiwalenty w C i Perlu i oba zostały ocenione na 19

Czy ktoś może mi wyjaśnić, dlaczego JavaScript ocenia odpowiedź jako 20, gdy inne języki oceniają ją na 19? Odpowiedź dostałem od testu nie był zbyt dla mnie jasne:

Przyrost ++ i ubytek - operatorzy mogą być umieszczone przed albo po argumencie. Jeśli operator przyrostu lub dekrementacji zostanie umieszczony przed operandem, operacja nastąpi natychmiast. Jeśli operand inkrementacji lub dekrementacji jest umieszczony za operandem, zmiana wartości argumentu nie jest widoczna, dopóki następnym razem operator nie uzyska dostępu do argumentu w programie. Tak więc, wyrażenie x + = X-- odpowiada x = x + 10, który ma wartość 20.

+3

Ach, jak ja nienawidzę tego rodzaju głupich pytań "gotcha"! Operatory przyrostowe i dekrementujące Postfix nie powinny nigdy występować w wyrażeniu zawierającym inne odniesienie do zmiennej, która jest (w | de) cremented. –

+6

w C, to jest niezdefiniowane zachowanie; jakikolwiek kod zawierający ten fragment jest z natury złamany – Christoph

+0

Czy '+ =' nie wprowadza punktu sekwencyjnego? –

Odpowiedz

6

Rozszerzenie komunikatu

x += x--; 

do bardziej opisowym kodu JS

x = x + (function(){ var tmp = x; x = x - 1; return tmp; })(); 

wynik ma sens, jak to będzie przetestuj na:

x = 10 + (function(){ var tmp = 10; x = 10 - 1; return tmp; })(); 

co 20 lat. Należy pamiętać, że JS ocenia wyrażenia od lewej do prawej, łącznie z przypisaniami złożonymi, tj. Wartość x jest buforowana przed wykonaniem x--.


Można także pomyśleć o tym w ten sposób: Zakładając, lewo-prawo kolejność oceny, JS analizuje zadanie jako

x := x + x-- 

natomiast Perl użyje

x := x-- + x 

I don nie widzą żadnych przekonywających argumentów za lub przeciw dowolnemu wyborowi, więc to po prostu pech, że różne języki zachowują się inaczej.

+1

Dzięki, to sprawia, że ​​jest dość jasne - nadal jest to denerwujące. Domyślam się, że jest tam jak grosz - wyobrażam sobie, że nikt nie użyłby takiego kodu, chyba że zostałby celowo zaciemniony! –

3

C/C++, co zmienna może być zmieniane tylko raz w każdej instrukcji (chyba dokładna terminologia to: tylko jeden raz między dwoma kodami, ale nie jestem pewien).

Jeśli piszesz

x += x--; 

Zmieniasz wartość x dwukrotnie:

  • jesteś zmniejszanie X za pomocą postfix - operator
  • ustawiasz wartość x korzystania przypisanie

Mimo że można to napisać, a kompilator nie będzie narzekał o tym (nie jestem pewien, możesz chcieć sprawdzić różne poziomy ostrzeżeń), wynik jest niezdefiniowany i może być różny w każdym kompilatorze.

+2

Termin, którego szukasz, to "punkt porządkowy" i różni się znacznie od "każdego stwierdzenia". – jamesdlin

+0

Tak, masz rację James. Dzięki za wskazanie tego. Więcej informacji o punktach sekwencji na Wikipedii: http://en.wikipedia.org/wiki/Sequence_point. – Patrick

1

W C, linia

x += x--; 

jest niezdefiniowany zachowania. Wydaje się, że danego kompilator traktuje to jak:

oldx = x--; 
x = x + oldx 

Jednak specyfikacji ECMAScript ma określić op= - i robi się wartość lewej po stronie przed oceniając prawo-ręcznego bok.

Więc byłoby to równoznaczne z:

oldx = x--; 
x = oldx + oldx 
1

Zasadniczo wartość x jest zmniejszana po przypisaniu. Ten przykład może uczynić go bardziej zrozumiałym (uruchomionym w konsoli Firebug).

var x = y =10;  
x += y--;   
console.log(x , y); // outputs 20 9 
Powiązane problemy