我刚刚在Javascript中遇到了关于预增量的'功能'。在我使用的所有其他语言中,它就像我认为的那样。例如。在C ++中:
#include <iostream>
int main()
{
int i = 0;
i += ++i;
std::cout << i << std::endl; // Outputs 2.
}
因此,++i
不会复制变量,因此输出为2。
在PHP中相同:
<?php
$i = 0;
$i += ++$i;
echo $i; // Outputs 2.
然而,在Javascript中:
var i = 0;
i += ++i;
console.log(i); // Outputs 1.
所以看起来在Javascript中,它会复制i
并且不会引用变量。这是故意的,如果是,为什么?
答案 0 :(得分:7)
来自EcmaScript标准:
11.4.4前缀增量运算符
生产UnaryExpression:++ UnaryExpression的评估如下:
- 让expr成为评估UnaryExpression的结果。
- 如果满足以下条件,则抛出SyntaxError异常:�
- Type(expr)是Reference is true
- IsStrictReference(expr)为真
- Type(GetBase(expr))是环境记录
- GetReferencedName(expr)是&#34; eval&#34;或者&#34;论证&#34;
- 让oldValue为ToNumber(GetValue(expr))。
- 让newValue成为将值1添加到oldValue的结果,使用与+运算符相同的规则(见11.6.3)。
- 调用PutValue(expr,newValue)。
- 返回newValue。
醇>
和
11.13.2化合物分配(op =)
生产AssignmentExpression:LeftHandSideExpression AssignmentOperator AssignmentExpression,其中AssignmentOperator是@ =,@代表上面指出的一个运算符,评估如下:
- 让lref成为评估LeftHandSideExpression的结果。
- 让lval成为GetValue(lref)。
- 让rref成为评估AssignmentExpression的结果。
- 让rval为GetValue(rref)。
- 设r是将operator @应用于lval和rval的结果。
- 如果满足以下条件,则抛出SyntaxError异常:
- Type(lref)是Reference is true
- IsStrictReference(lref)为真
- 类型(GetBase(lref))是环境记录
- GetReferencedName(lref)是&#34; eval&#34;或者&#34;论证&#34;
- 调用PutValue(lref,r)
醇>
因此,var i = 0; i += ++i
是:
i = 0;
lvalue = value(i), which is 0;
rvalue = value(++i), which is: increment i, then value of i (1);
thus, rvalue = 1;
i = lvalue (0) + rvalue (1), which is 1.
完全符合规范。
但是,在C ++中,这被明确定义为未定义的行为,因此在不同的编译器上,您可能也会获得1.或99.或者它可能会使您的计算机着火。所有这些都是符合标准的编译器。因此,大多数人会建议你只在声明中使用一次/后增量变量。
答案 1 :(得分:0)
我认为这是因为javascript看到var i = 0; i += ++i;
就是这样:
var i = 0;
++i = 1;
i += 1;
这是因为++i
在执行+=
之前将i变为1,所以它0 + 1 = 1
事实上,我越是想到它,为什么还要做其他事情?
发生了两项任务,一项必须在另一项之前完成。所以这两个选项可能是:
或