0

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

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

我期待新的价值a应该是3和价值b应该是5。但我的价值观是a = 0 and b = 5

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

所以我尝试了这个

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

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

4

5 回答 5

2

这是解释,我希望它很清楚,因为它不是那么明显。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

然后从下到上处理树。

于 2013-09-27T08:09:49.757 回答
1
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
于 2013-09-27T07:53:57.337 回答
1

正如你所说,表达式是从左到右计算的,这意味着第一次遇到 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

于 2013-09-27T08:05:15.673 回答
0
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

如您所料。

于 2013-09-27T08:07:31.903 回答
0
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(新 a) - 3(旧 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(最终) = 5(新 b) - 8(新 a) = -3

新 a = -3,新 b = 5

我希望它是可读的:D

于 2013-09-27T08:12:14.707 回答