JavaScript问题辨析之——(a+++a)与(a+a++)

413 阅读2分钟

一、问题简述

在JavaScript中,存在着广泛且容易记错的问题,那就是:a+++a和a+a++的计算顺序,究竟是怎样的?

二、详细辨析

1.a+++a的实际运算顺序

首先让我们来回顾一下JavaScript中的运算符(操作符)优先级,下图是从MDN中截取的运算符优先级表,可以看出,“+”的优先级实际上是要低于“++”的。

Operator Precedence of JS.PNG

然而“++”分为前置(++a)和后置(a++)两种,从表中可以看出,后置(a++)的优先级是要高于前置(++a)的,所以三者的优先级从高到低的排序应该是:"a++ > ++a > +"

所以a+++a的运算顺序其实是等同于:(a++) +a 的,我们来实际测试一下这个结论:

1.PNG

2.PNG

可以从上图中看出,二者的运算结果是一致的,论证了我们的结论。

2.a+a++的实际运算顺序

通过上节我们列出的优先级表以及分析出的数据,可以看出,a++的优先级是高于+的,那么很容易得出这样一个结论,即:a+a++的实际运算顺序应该等同于:a+(a++),让我们继续来实际测试一下:

3.PNG

可以从上图中看出,二者的运算结果是一致的,事实又一次论证了我们的结论。

3.两者的差异

从a+++a和a+a++的实际运算结果不难看出,两者的运算结果并不一致,这是为什么呢?

虽然,两者的运算顺序都是,先运算a++,再+a,但是因为a++和+a/a+在表达式的位置不同,对运算结果产生了影响。

即:

      +
    /   \
   /     \
 a        a++

编译器的处理过程:
1. push(a), a入栈(1)
2. push(a++),即push(1),之后 a自增变成2
3. result = pop()+pop(), 出栈两个操作数(1,1)相加,得到2

      +
    /   \
   /     \
  a++     a

编译器的处理过程:
1. push(a++), 即push(1),之后 a自增变成2
2. push(a),即push(2)
3. result = pop()+pop(), 出栈两个操作数(1,2)相加,得到3