admin管理员组

文章数量:1290102

I'm studying for an exam on JavaScript at the moment. I've also got a little knowledge of C and Perl so I'm familiar with prefix and postfix operators in all three languages.

I did an online practice exam for it and one mistake I made was in evaluating the following code:

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

Now, I thought it would evaluate to 19 because it would be 10 + 10, then subtract 1 to make 9. But the feedback I got was that it was wrong and it actually evaluates to 20. I thought that sounded a bit suspicious so I tested it out in an HTML document, and it came out with 20 again. I then tried the equivalents in C and Perl and both evaluated to 19.

Can anyone explain to me why JavaScript evaluates the answer as 20 when other languages evaluate it to 19? The answer I got from the test wasn't too clear to me:

The increment ++ and decrement -- operators can be placed either before or after an operand. If the increment or decrement operator is placed before the operand, the operation occurs immediately. If the increment or decrement operator is placed after the operand, the change in the operand's value is not apparent until the next time the operand is accessed in the program. Thus the expression x += x-- is equivalent to x = x + 10 which evaluates to 20.

I'm studying for an exam on JavaScript at the moment. I've also got a little knowledge of C and Perl so I'm familiar with prefix and postfix operators in all three languages.

I did an online practice exam for it and one mistake I made was in evaluating the following code:

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

Now, I thought it would evaluate to 19 because it would be 10 + 10, then subtract 1 to make 9. But the feedback I got was that it was wrong and it actually evaluates to 20. I thought that sounded a bit suspicious so I tested it out in an HTML document, and it came out with 20 again. I then tried the equivalents in C and Perl and both evaluated to 19.

Can anyone explain to me why JavaScript evaluates the answer as 20 when other languages evaluate it to 19? The answer I got from the test wasn't too clear to me:

The increment ++ and decrement -- operators can be placed either before or after an operand. If the increment or decrement operator is placed before the operand, the operation occurs immediately. If the increment or decrement operator is placed after the operand, the change in the operand's value is not apparent until the next time the operand is accessed in the program. Thus the expression x += x-- is equivalent to x = x + 10 which evaluates to 20.

Share Improve this question edited Feb 11, 2020 at 0:09 user207421 311k44 gold badges321 silver badges489 bronze badges asked Feb 14, 2010 at 22:28 Matthew DalyMatthew Daly 9,4762 gold badges45 silver badges86 bronze badges 5
  • 3 Ah, how I hate this kind of stupid "gotcha" questions! Postfix increment/decrement operators should never occur in an expression containing another reference to the variable being (in|de)cremented. – Max Shawabkeh Commented Feb 14, 2010 at 22:33
  • 6 in C, this is undefined behaviour; any code which contains this snippet is inherently broken – Christoph Commented Feb 14, 2010 at 22:34
  • Does += not introduce a sequence point? – Anon. Commented Feb 14, 2010 at 22:47
  • @Anon: no, it doesn't - the end of the statement is the next sequence point – Christoph Commented Feb 14, 2010 at 22:53
  • Ah, that makes sense. I have corrected that part of my answer. – Anon. Commented Feb 14, 2010 at 22:56
Add a ment  | 

4 Answers 4

Reset to default 6

Expanding the statement

x += x--;

to the more verbose JS code

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

the result makes perfect sense, as it will evaluate to

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

which is 20. Keep in mind that JS evaluates expressions left-to-right, including pound assignments, ie the value of x is cached before executing x--.


You could also think of it this way: Assuming left-to-right evaluation order, JS parses the assignment as

x := x + x--

whereas Perl will use

x := x-- + x

I don't see any convincing arguments for or against either choice, so it's just bad luck that different languages behave differently.

In C/C++, every variable can only be changed once in every statement (I think the exact terminology is: only once between two code points, but I'm not sure).

If you write

x += x--;

you are changing the value of x twice:

  • you are decrementing x using the postfix -- operator
  • you are setting the value of x using the assignment

Although you can write this and the piler won't plain about it (not sure, you may want to check the different warning levels), the oute is undefined and can be different in every piler.

Basically, the value of x is decemented after assignment. This example might make it clearer (run in Firebug console)

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

In C, the line

x += x--;

is undefined behaviour. It seems like your particular piler is treating it like:

oldx = x--;
x = x + oldx

However, the ECMAScript specification does specify op= - and it gets the value of the left-hand-side before evaluating the right-hand-side.

So it would be equivalent to:

oldx = x--;
x = oldx + oldx

本文标签: Why is JavaScript39s postincrement operator different from C and PerlStack Overflow