【问题标题】:Can somebody explain how javascript Arithmetic expressions work?有人可以解释一下javascript算术表达式是如何工作的吗?
【发布时间】:2013-10-03 10:26:44
【问题描述】:

让我们评估此代码以交换两个变量:

var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );

我期望a 的新值应该是3b 的值应该是5。但我的值为a = 0 and b = 5;

我去阅读了 EcmaScript 算术表达式,发现它将从左到右进行计算。 (但不完全清楚)。

所以我尝试了这个

var a = 5, b = 3; 
a = ( ( b = ( a = a+b ) - b ) - a );

现在我收到了a = -3 and b = 5。有人可以解释一下为什么会这样吗?

【问题讨论】:

    标签: javascript arithmetic-expressions


    【解决方案1】:

    这里是解释,我希望它清楚,因为它不是那么明显。 JS 和所有其他语言创建一个树来评估表达式。树会根据每个运算符的位置和大括号为每个运算符分配一个权重。

    首先,这是 JS 处理表达式的步骤:

    Step 0. a = ( a - ( b = ( a = a+b ) - b ) );   a=5, b=3
    Step 1.                   a = a+b              a=8, b=3
    Step 2.             b = a - b                  a=8, b=5 
    Step 3. a = a - b                              a=0, b=5
    

    在每一步它处理一个运算符。

    这是它根据你的表达式创建的树:

        =
      /   \
     a     - 
         /    \
       a       =
              /  \   
             b    -            
                 / \
                =   b
               /  \
              a    +
                  / \
                 a   b
    

    然后从下到上处理树。

    【讨论】:

    • 但是,在第三步a = a-b 应该给我a=3 and b=5 的结果。不是吗?因为step2把a and b的值改成了a = 8 and b =3。我有点困惑
    • 看看我的回答:stackoverflow.com/a/19045816/1324929。 @KLiFF 没有提到的是,对于赋值,第一步是右侧的表达式评估。因此,a = ( a -( b = ( a = a+b ) - b ) ) 变为 a = ( 5 -( b = ( a = 5+3 ) - 3 ) )。之后,右侧,从内圆到外圆,a = 5+3,a 变为 8,b = 8-3,b 变为 5,最后 a = 5-5,a 变为 0,b 保持 5。
    • 不完全是。树从左到右处理,否则在您的第一个左节点中 a = 8。
    • 确实很混乱,但解释如下:左边的a已经被计算过,值为5,右边的a是右边的计算结果树的分支,值为 8。所以实际上有一个 a 和一个 a'。
    • 这棵树是如何被精确处理的?是从下到上还是从左到右?我读到算术表达式是从左到右计算的。如果我在这里应用相同的逻辑,那么它是有道理的..它会产生正确的输出..我只需要再澄清一点,在处理左节点时,它应该在移动到右节点之前处理它的所有子节点。 . 不是吗?
    【解决方案2】:

    如你所说,表达式是从左到右计算的,意思是第一次遇到 a 时,它的值仍然是 5。这归结为:

    var a = 5, b = 3; 
    a = ( a -( b = ( a = a+b ) - b ) );
    a = 5 - (b = (a=(5+3)) - b);
    a = 5 - (b = 8 - b);
    a = 5 - 5; AND b = 5
    

    在第二个中,a 值在赋值后被评估,因为它在右边

    var a = 5, b = 3;
    a = ( ( b = ( a = a+b ) - b ) - a );
    a = ( ( b = 8 - b ) - a ); AND a = 8
    a = ( 5 - 8 ); AND a = 8; AND b = 5;
    a = - 3;
    

    这一切都归结为操作数的评估顺序。

    通常在第一种情况下,a 被评估为 5,然后 b = ( a = a+b ) - b 被评估,并且仅在此评估期间 a 的值会发生变化,但不会向后移植。

    在第二个例子中,先计算( b = ( a = a+b ) - b ),将a的值改为8,然后计算a,发现是8

    一个更简单的例子是:

    var a = 5
    a = a + (a = 2)
    // a = 7
    

    a 被评估为 5,然后(a = 2) 被评估为 2 并且 a 被设置为 2,然后5+2 被评估并且 a 被设置为 7。

    另一方面:

    var a = 5
    a = (a = 2) + a
    // a = 4
    

    (a = 2) 被评估为 2 并且 a 被设置为 2,然后 a 被评估为 2,然后2+2 被评估并且 a 被设置为 4

    【讨论】:

      【解决方案3】:
      var a = 5, b = 3;
      a = ( ( b = ( a = a+b ) - b ) - a );
      

      它将以这种方式运行。

      a = a + b //8
      b = a - b //8-3=5
      a = b - a //5-8=-3
      

      【讨论】:

      • 为什么 a = ( a -( b = ( a = a+b ) - b ) );给了我a=0 and b=5
      • 是的,我最好的猜测是 a 在表达式 (a = a+b) 之前设置为 5,所以 a 保持为 5。
      【解决方案4】:
      var a = 5, b = 3; 
      a = ( a -( b = ( a = a+b ) - b ) );
      

      1) a = a(5) - (表达式的其余部分,其中 2 个部分将很快计算出来)

      2) b = (a = a+b // 还没有计算出来) - b (也就是3,因为新的b还没有改变)

      3) a = 5(a) + 3(b) = 8

      4) b(我们回到第 2 点) = 8(new a) - 3(old b) = 5

      5) a(点 1) = 5(旧 a) - 5(新 b) = 0

      新 a = 0,新 b = 5

      var a = 5, b = 3; 
      a = ( ( b = ( a = a+b ) - b ) - a );
      

      1) b = ( a = a+b ) - 3(b)

      2) a = 5(a) + 3(b) = 8

      3) b = 8(新 a) - 3(旧 b) = 5

      4) a(final) = 5(new b) - 8(new a) = -3

      新 a = -3,新 b = 5

      我希望它是可读的:D

      【讨论】:

        【解决方案5】:
        a = ( a -( b = ( a = a+b ) - b ) ) 
        

        类似

        a = ( 5 -( b = ( a = 5+3 ) - 3 ) ) // a = 8
        // a = ( 5 - ( b = 8 - 3 ) ) // b = 5
        // a = ( 5 - 5 ) // a = 0
        

        意味着它将一次性用相同的初始值替换 = 左侧的 a 和 b, 和这个序列不相似

        a = a+b; // a = 8
        b = a-b; // b = 5
        a = a-b; // a = 3
        

        如你所愿。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多