Javascript中的预增量 [英] Pre increment in Javascript
问题描述
我刚刚在Javascript中遇到了关于预增量的'功能'。在我使用的所有其他语言中,它就像我认为的那样。例如。在C ++中:
I've just encountered a 'feature' in Javascript regarding pre-increments. In all other languages I've used, it goes like I thought it would. E.g. in C++:
#include <iostream>
int main()
{
int i = 0;
i += ++i;
std::cout << i << std::endl; // Outputs 2.
}
所以, ++ i
不复制变量,因此输出为2.
So, ++i
doesn't make copy of the variable, hence the output is 2.
与PHP相同:
<?php
$i = 0;
$i += ++$i;
echo $i; // Outputs 2.
但是,在Javascript中:
However, in Javascript:
var i = 0;
i += ++i;
console.log(i); // Outputs 1.
所以在Javascript中它看起来像是 i
并且不引用该变量。这是故意的,如果是,为什么?
So it looks like that in Javascript, it makes copy of i
and doesn't reference the variable. Is this intentional and if yes, why?
推荐答案
来自EcmaScript标准:
From EcmaScript standard:
11.4.4前缀增量运算符
11.4.4 Prefix Increment Operator
生产UnaryExpression:++ UnaryExpression的计算方法如下:
The production UnaryExpression : ++ UnaryExpression is evaluated as follows:
- 让expr成为评估UnaryExpression的结果。
- 如果满足以下条件,则抛出一个SyntaxError异常:
- Type(expr)为Reference is true
- IsStrictReference(expr)为真
- 类型(GetBase(expr))是环境记录
- GetReferencedName(expr)是eval或arguments
- Let expr be the result of evaluating UnaryExpression.
- Throw a SyntaxError exception if the following conditions are all true: �
- Type(expr) is Reference is true
- IsStrictReference(expr) is true
- Type(GetBase(expr)) is Environment Record
- GetReferencedName(expr) is either "eval" or "arguments"
和
11.13.2复合赋值(op =)
11.13.2 Compound Assignment ( op= )
生产AssignmentExpression:LeftHandSideExpression AssignmentOperator AssignmentExpression,其中AssignmentOperator是@ =和@代表上面指出的一个运算符,评估如下:
The production AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression, where AssignmentOperator is @= and @ represents one of the operators indicated above, is evaluated as follows:
- 让lref成为评估LeftHandSideExpression的结果。
- 让lval成为GetValue(lref)。
- 让rref成为评估AssignmentExpression的结果。
- 让rval为GetValue(rref)。
- 设r是将operator @应用于lval和rval的结果。
- 如果以下条件都为真,则抛出一个SyntaxError异常:
- Type(lref)is Reference is true
- IsStrictReference(lref)为真
- 类型(GetBase(lref))是环境记录
- GetReferencedName(lref)要么是eval或arguments
- Let lref be the result of evaluating LeftHandSideExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating AssignmentExpression.
- Let rval be GetValue(rref).
- Let r be the result of applying operator @ to lval and rval.
- Throw a SyntaxError exception if the following conditions are all true:
- Type(lref) is Reference is true
- IsStrictReference(lref) is true
- Type(GetBase(lref)) is Environment Record
- GetReferencedName(lref) is either "eval" or "arguments"
因此, 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.或者它可以设置为规范。
Completely according to spec.
你的电脑着火了。所有这些都是符合标准的编译器。因此,大多数人会建议你只在声明中使用一次前/后增量变量。
However, in C++, this is specifically defined to be undefined behaviour, thus on a different compiler you might also get 1. Or 99. Or it could set your computer on fire. All of those would be standard-compliant compilers. Thus, most people will recommend you only use pre/post-incremented variable once in a statement.
这篇关于Javascript中的预增量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!