Chained assignment of variables with operators in JavaScript

后端 未结 2 1901
感动是毒
感动是毒 2021-01-25 11:25

I want to do something to a couple of variables using operators in quick succession. I don\'t think what I want to do is important as such; my question is more about th

相关标签:
2条回答
  • 2021-01-25 11:36

    According to ECMA-262 5th ed. 11.13.2,Compound Assignment Operators are evaluated as below:

    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).
    8. Return r.

    The last example is evaluated as below:

    1. Let a be lref, Let (b += (a += b)) be rlef.
    2. Evaluate a and Let lval be the result of it(9).
    3. Evaluate (b += (a += b)) and Let rval be the result of it.
       a. Let b be lref_, Let (a += b) be rlef_.   
       b. Evaluate b and let lval_ be the result of it(2).
       c. Evaluate (a += b) and let rval_ be the result of it.
         A. Let a be lref__, let b be rlef.
         B. Evaluate a and Let lval__ be the result of it(9).
         C. Evaluate b and Let rval__ be the result of it(2).
         D. Put lval__ + rval__ (means 9+2) to lref__(a) and return it.   
       d. Put lval_ + rval_ (means 2+11) to lref_(b) and return it.
    4. Put lval + rval (means 9+13) to lref(a) and return it.
    

    then we can get a === 22, b === 13.

    0 讨论(0)
  • 2021-01-25 11:54

    I think (not sure, although this is counter-intuitive) you can imagine:

    a += (b += (a += b));
    

    being written as:

    a = a + (b += (a += b));
    

    Although the plus + operator has right to left associativity, JavaScript expressions are evaluated from left-to-right, so a is evaluated first which is 9 now, then (b += (a += b)) is evaluated to 13.

    Now the + operator adds from right-to-left, thus adding 13 to 9 and giving us 22.

    EDIT: I am not gonna comment directly on your questions because I feel confused by reading them :).

    Instead I am gonna try to explain this differently. I think the main source of your confusion comes from the difference between operator precedence, associativity and order of evaluation.

    I really advise you to read the part on the Order of Evaluation (4.7.7 in the book, which is a great book by the way).

    Let's go with an example first:

    var x =1, y = 2, z = 3;
    var alpha = (z=4) + y * z;
    console.log(x); // 1
    console.log(y); // 2
    console.log(z); // 4
    console.log(alpha);  // 12
    

    In this example, although the multiplication operator * has higher precedence than the summation operator +, the the evaluation of the different components of the entire expression is still from left-to-right.

    alpha on the left is declared and created first, then (z=4) is evaluated, then y is evaluated to 2. Now z is evaluated again which results in 4, notice that this is the new value which is caused by the side-effect of assigning 4 to z earlier in the expression, remember (z=4).

    This results in an overall value for alpha that is equal to 12.

    Now back to our original expression:

    a += (b += (a += b));
    

    a on the left is evaluated first which is 9 now, then the first b to the left is evaluated which is now 2, now the second a is evaluated which is 9 also, then the last b to the right is evaluated which is again 2.

    Now starts the real work, because of the parentheses the last (a += b) is evaluated so now we have a = 11, then (b += (a += b)) is evaluated which is now 13, now this value is summed the value already evaluated which is 9 resulting in 22.

    If it hasn't happened this way, this would mean that a on the left side of = would have been evaluated twice which is not the case.

    Summary: You can't update the value of an already evaluated expression.

    I hope this can clear this for you, if you have any further questions then feel free to ask :)

    0 讨论(0)
提交回复
热议问题