admin管理员组

文章数量:1317564

I've just encountered a 'feature' in Javascript regarding pre-increments. In all other languages I've used, it goes like I thought it would. E.g. in C++:

#include <iostream>

int main()
{
    int i = 0;

    i += ++i;

    std::cout << i << std::endl; // Outputs 2.
}

So, ++i doesn't make copy of the variable, hence the output is 2.

Same in PHP:

<?php

$i = 0;

$i += ++$i;

echo $i; // Outputs 2.

However, in Javascript:

var i = 0;

i += ++i;

console.log(i); // Outputs 1.

So it looks like that in Javascript, it makes copy of i and doesn't reference the variable. Is this intentional and if yes, why?

I've just encountered a 'feature' in Javascript regarding pre-increments. In all other languages I've used, it goes like I thought it would. E.g. in C++:

#include <iostream>

int main()
{
    int i = 0;

    i += ++i;

    std::cout << i << std::endl; // Outputs 2.
}

So, ++i doesn't make copy of the variable, hence the output is 2.

Same in PHP:

<?php

$i = 0;

$i += ++$i;

echo $i; // Outputs 2.

However, in Javascript:

var i = 0;

i += ++i;

console.log(i); // Outputs 1.

So it looks like that in Javascript, it makes copy of i and doesn't reference the variable. Is this intentional and if yes, why?

Share Improve this question edited May 29, 2014 at 10:02 Girish 12.1k3 gold badges36 silver badges53 bronze badges asked May 29, 2014 at 10:00 nhaa123nhaa123 9,81811 gold badges45 silver badges63 bronze badges 4
  • Maybe not an explanation, or even a solution, but certainly a good read: stackoverflow./questions/971312/… – emerson.marini Commented May 29, 2014 at 10:06
  • In C++, this isn't even meaningful. it's undefined behavior. – The Paramagnetic Croissant Commented May 29, 2014 at 10:08
  • Another good read: javascript.about./od/hintsandtips/a/… – emerson.marini Commented May 29, 2014 at 10:11
  • stackoverflow./questions/1546981/… – Abdennour TOUMI Commented May 29, 2014 at 10:23
Add a ment  | 

2 Answers 2

Reset to default 7

From EcmaScript standard:

11.4.4 Prefix Increment Operator

The production UnaryExpression : ++ UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression.
  2. Throw a SyntaxError exception if the following conditions are all true: �
    • Type(expr) is Reference is true
    • IsStrictReference(expr) is true
    • Type(GetBase(expr)) is Environment Record
    • GetReferencedName(expr) is either "eval" or "arguments"
  3. Let oldValue be ToNumber(GetValue(expr)).
  4. Let newValue be the result of adding the value 1 to oldValue, using the same rules as for the + operator (see 11.6.3).
  5. Call PutValue(expr, newValue).
  6. Return newValue.

and

11.13.2 Compound Assignment ( op= )

The production AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression, where AssignmentOperator is @= and @ represents one of the operators indicated above, is evaluated as follows:

  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let lval be GetValue(lref).
  3. Let rref be the result of evaluating AssignmentExpression.
  4. Let rval be GetValue(rref).
  5. Let r be the result of applying operator @ to lval and rval.
  6. Throw a SyntaxError exception if the following conditions are all true:
    • Type(lref) is Reference is true
    • IsStrictReference(lref) is true
    • Type(GetBase(lref)) is Environment Record
    • GetReferencedName(lref) is either "eval" or "arguments"
  7. Call PutValue(lref, r)

Thus, var i = 0; i += ++i is:

i = 0;
lvalue = value(i), which is 0;
rvalue = value(++i), which is: increment i, then value of i (1);
thus, rvalue = 1;
i = lvalue (0) + rvalue (1), which is 1.

Completely according to spec.

However, in C++, this is specifically defined to be undefined behaviour, thus on a different piler you might also get 1. Or 99. Or it could set your puter on fire. All of those would be standard-pliant pilers. Thus, most people will remend you only use pre/post-incremented variable once in a statement.

I believe this is because javascript see's var i = 0; i += ++i; as this:

var i = 0;
++i = 1;
i += 1;

It's because the ++i turns i into 1 before performing +=, so it's 0 + 1 = 1

In fact, the more I think about it, why would it do anything else?

There are two assignments taking place, and one has to be done before the other. So the two options would be either:

  • do ++i first, and make it i = i + 1 where i starts at 0 and equates to 1

or

  • do the += first, and make it i = 0 + (++i) which would also equate to 1

本文标签: Pre increment in JavascriptStack Overflow