代码中语句的顺序和 js 引擎执行语句的顺序并不一定要一致。

    1. var a, b;
    2. a = 10; b = 30;
    3. a = a + 1;
    4. b = b + 1;
    5. console.log( a + b ); // 42

    这段代码中没有显式的异步(除了前面介绍过的很少见的异步 I/O !),所以很可能它的执 行过程是从上到下一行行进行的。
    但是,js 引擎在编译这段代码之后可能会发现通过(安全地)重新安排这些语句的顺序有可能提高执行速度。重点是,只要这个重新排序是不可见的,一切都没问题。比如,引擎可能会发现,其实这样执行会更快:

    1. var a, b;
    2. a = 10; a++;
    3. b = 30; b++;
    4. console.log( a + b ); // 42

    或者这样:

    1. var a, b;
    2. a = 11; b = 31;
    3. console.log( a + b ); // 42

    或者甚至这样:

    1. // 因为a和b不会被再次使用
    2. // 我们可以inline,从而完全不需要它们!
    3. console.log( 42 ); // 42

    前面的所有情况中,js 引擎在编译期间执行的都是安全的优化,最后可见的结果都是一样的。
    但是这里有一种场景,其中特定的优化是不安全的,因此也是不允许的(当然,不用说这其实也根本不能称为优化):

    1. var a, b;
    2. a = 10; b = 30;
    3. // 我们需要a和b处于递增之前的状态!
    4. console.log( a * b ); // 300
    5. a = a + 1;
    6. b = b + 1;
    7. console.log( a + b ); // 42

    还有其他一些例子,其中编译器重新排序会产生可见的副作用(因此必须禁止),比如会产生副作用的函数调用(特别是 getter 函数),或 ES6 代理对象。

    1. function foo() {
    2. console.log( b );
    3. return 1;
    4. }
    5. var a, b, c;
    6. // ES5.1 getter字面量语法
    7. c= {
    8. get bar() {
    9. console.log( a );
    10. return 1;
    11. } };
    12. a = 10; b = 30;
    13. a += foo();
    14. b += c.bar;
    15. // 30 // 11
    16. console.log( a + b ); // 42

    如果不是因为代码片段中的语句 console.log(..)(只是作为一种方便的形式说明可见的副作用),js 引擎如果愿意的话,本来可以自由地把代码重新排序如下:

    1. // ...
    2. a = 10 + foo();
    3. b = 30 + c.bar;
    4. // ...