关于Math.PI、前自增和后自增

有这么一个题目,说bt其实也不bt,为了重点突出其中的意图,特意加上了括号:

var a = (++Math.PI);
var b = (Math.PI++);
var c = Math.PI = (++Math.PI);
var d = Math.PI = (Math.PI++);
var e = Math.PI = (Math.PI + 1);

执行完后,a、b、c、d、e的值分别是什么呢?如果学校里学的C语言基础好的话,应该可以知道答案。你不妨先写下答案,我们再来看看ECMA的规范。

在ECMA-262中,对于Math.PI的说明是这样的:

15.8.1.6

The number value for π, the ratio of the circumference of a circle to its diameter, which is approximately 3.1415926535897932.

This property has the attributes { DontEnum, DontDelete, ReadOnly }.

很清楚,ReadOnly,那么你给Math.PI赋值是没有用的。

再看看关于前自增(Prefix Increment):

11.4.4 Prefix Increment Operator

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

1. Evaluate UnaryExpression.
2. Call GetValue(Result(1)).
3. Call ToNumber(Result(2)).
4. Add the value 1 to Result(3), using the same rules as for the + operator (see 11.6.3).
5. Call PutValue(Result(1), Result(4)).
6. Return Result(4).

注意,前自增返回的是第四步的结果,也就是自增1以后的值。因此,对于a来说,就是先取Math.PI的值,然后转化为Number,然后加1,返回的就是Math.PI的值加1以后的结果。因此,a是4.141592653589793.

再看看关于后缀自增(Prefix Increment):

11.3.1 Postfix Increment Operator

The production PostfixExpression : LeftHandSideExpression [no LineTerminator here] ++ is evaluated as follows:

1. Evaluate LeftHandSideExpression.
2. Call GetValue(Result(1)).
3. Call ToNumber(Result(2)).
4. Add the value 1 to Result(3), using the same rules as for the + operator (see 11.6.3).
5. Call PutValue(Result(1), Result(4)).
6. Return Result(3).

和上面的不同,返回第三步的结果,即没有自增之前的结果,因此返回3.141592653589793.

再来看看两个连续赋值的三个表达式,由于赋值运算是右结合运算,因此这三个表达式相当于:

var c = (Math.PI = (++Math.PI));
var d = (Math.PI = (Math.PI++));
var e = (Math.PI = (Math.PI + 1));

而对于赋值运算,在ECMA-262中是这样描述的:

11.13.1 Simple Assignment ( = )

The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:

1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

赋值后,返回第三步的结果,即语句右边的表达式的结果。因此,这里c、d、e的结果就很明显了:

c = 4.141592653589793;
d = 3.141592653589793;
e = 4.141592653589793;

这里还要注意一点什么?a++ 和 a=a+1 不一样~

1 comment on “关于Math.PI、前自增和后自增”

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据