后缀增量在JavaScript中遇到加法(+)运算符时是如何工作的

How postfix increment work when it meet addition(+) operator in JavaScript?

本文关键字:运算符 何工作 工作 JavaScript 遇到 后缀      更新时间:2023-09-26

首先,我知道后面讨论的表达式有side-effects,不应该在生产环境中使用。我只是想通过他们了解JavaScript。所有这些都在CCD_ 3下进行了测试。

var a = 42;
var b = "42";
a + ++b; // result is 85 

以下是我对a + ++b、的理解

根据操作员优先级,Prefix Increment (++)(优先级15)的优先级高于Addition(+)(优先级13)。++b可以解析为var ToNumber(GetValue(expr))43,参见12.5.7 Prefix Increment Operator。则CCD_ 11的结果可能是CCD_。

然而,

var a = 42;
var b = "42";
a++ + b; // "4242"

为什么a++ + b的结果是"4242"

我试图理解结果"4242",似乎a++首先返回42,然后对于42 + '42'42将首先是'42' var ToString(),参见12.7.3 The Addition operator ( + )。则结果可以是CCD_ 23。

但这似乎违反了规则:Postfix increment(优先级16)高于Addition(优先级13)???

var a = 42;
var b = "42";
a +++b; // "4242" 

如何解析a +++b;

哈哈,这是一个棘手的问题!

修复后增量返回相同的值,然后增量变量。这是我所知道的每种语言的默认行为。

所以,当你这样做时(警告:这不是一个有效的表达式,它只是为了展示这个想法):

42++ + "42"

真正发生的是:

  1. 第一个42由++运算符返回
  2. 然后42增加到43
  3. 然后42(表达式的结果值)被强制转换为字符串
  4. 然后将两个操作数连接起来

编辑#1:

如果你这样做:

var a = 42;
var b = "42";
a + b++; // result is 84

测试一下!

编辑#2:

因此,我们得出结论,您的问题与运算符优先级无关(:

javascript与其他语言在后增量和前增量方面存在差异。也就是说,这些运算符可以与操作数用一个空格分隔。例如:

var a = 42;
++ a;

注意++和a之间的空格,这也适用于a ++
因此,当javascript开始解析语句时,它会获取操作数或运算符,并将其存储在堆栈中,然后找到使用它的机会。我希望您知道语言是如何从左到右或从右到左解析语句的。Javascript从左到右对其进行解析
因此,当您编写a +++b时,它从左侧开始解析,

找到一个:在堆栈中推一个;堆栈:[a]
在堆栈中找到+:push+;堆栈:[a,+]
Found+:pop+和一个from stack和apply操作数,并推送堆栈上的结果(现在堆栈在内存中只有一个,而不是++,因为增量后);堆栈[a]
Found+:推栈;堆栈:[a,+]
从堆栈中找到b:pop+和a,应用操作数并将结果推送到堆栈上;堆栈:[b]

没有更多的操作数或运算符,所以它给出的结果是a+b,并且作为对a的后增量的结果,如果你想在添加之前增加b,你可以试试这个:

a + ++b

这将从++中分离+,现在javascript知道在哪里应用增量。

当然,作为一元运算符的递增/递减运算符优先于Chrome0(加法/级联)二进制操作符,但我认为这里的有趣问题是强制。让我解释一下:

为什么a+++b的结果是4242?

a是数字42,b是字符串'42')

这是因为当您将increment运算符应用于具有数字值('42')的字符串时,结果会被强制为数字(42)。

因此,现在我们剩下一个表达式number + string(42+'42'):在这种情况下,+运算符将连接(将数字42强制转换为字符串'42',得到字符串'4242')。

另一方面:在第一个例子中,a + ++ba是数字42,b是字符串'42')-b将在增量后被强制为数字,留下number + number(42+43)-因此+运算符将执行addition,而不是级联(42+43=85)

关于下一个问题:

a+++b;被解析?

由于用空格分隔变量和增量运算器是合法的,因此解析器将查看a +++b并首先查看a++

此外,由于+运算符在其两个操作数之间不需要空格,因此解析器将使用+运算符正确地分离操作数a++b。因此a +++b;将被解析为a++ + b

@zangw没有什么比++优先级更高的了++b是一个预增量运算符,+是一个算术运算符++b表示首先更改操作数的值,然后使用与a++相矛盾的值。++总是与一个操作数一起出现,+介于两个操作数之间,后面的操作数是一个解压缩。希望你拿到了?

好问题,请检查此ecma标准12.7.3.1(步骤11)

11. If Type(lprim) is String or Type(rprim) is String, then
   a. Let lstr be ToString(lprim).
   b. ReturnIfAbrupt(lstr).
   c. Let rstr be ToString(rprim).
   d. ReturnIfAbrupt(rstr).
   e. Return the String that is the result of concatenating lstr and rstr

如果运算符中的任一个是CCD_ 51,则两者都被转换为字符串。

这实际上与运算符优先级无关;它与词法分析/解析有关,这种情况早在运算符优先级等概念应用之前就发生了。和许多其他语言一样,JavaScript的lexer是"贪婪的",这意味着在选择"+"answers"++"时,总是会选择更长的符号。

这个问题很好,但答案是:)。

    var a = 42;
    var b = "42";
    console.log(a +++b); // "4242" 
    console.log(a);
    console.log(b);
    console.log('A is 43 now... so postfix on A, then + B');

名称的post部分不仅来自运算符的物理存在(在操作数之前或之后),还来自变量实际更新的时间。

Postfix增量在这里定义为:

[增量(++)运算符,]如果使用后缀,在操作数后面加运算符(例如,x++),则它返回递增之前的值。

因此,它将值返回到串联,然后递增变量。也就是说,递增后的变量在将原始值返回到加法运算后进行更新。

你的问题的答案在于了解变量何时更新。

运算符优先级是有意义的,因为后缀仍然是先计算的,然后是进行加法运算。但是,后缀的变量在值返回给加法之前不会更新。因此,结果为"4242"。