让我们评估此代码以交换两个变量:
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
。有人可以解释一下为什么会这样吗?
答案 0 :(得分: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
然后从下到上处理树。
答案 1 :(得分: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
答案 2 :(得分: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
,并且仅在此评估期间更改值,但不会向后移植。
在第二个示例中,首先评估( 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 :(得分: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
如你所料。
答案 4 :(得分: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