• JS运行三部曲(预编译)


    JS运行的三个步骤:

    1. 语法分析
    2. 预编译
    3. 解释执行

    语法分析:通俗来说就是通篇检查你的代码有没有语法错误,有语法错误的话,程序是不会执行的

    解释执行:也就是程序读一句执行一句

    最重点的也就是预编译了,那么预编译到底是什么?它发什么在什么时候?

    先来段代码压压惊

    function fn (a) {
        console.log(a)
        var a = 123;
        console.log(a)
        function a () {}
        console.log(a)
        console.log(b);
        var b = function () {}
        console.log(b);
        function d () {}
        console.log(d)
    }
    fn(1)

    这是打印结果

    ƒ a() {}
    123
    123
    undefined
    ƒ () {}
    ƒ d() {}

    是不是有些地方有点懵逼和意外,其实这就是预编译捣的鬼,预编译就是在函数执行之前,在你的内存中申请一点空间,存放变量和函数
    下面说说预编译到底是怎样的过程,也就是上面函数到底发生了什么

    预编译过程:

    1. 创建AO对象(Active Object)
    2. 找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为undefined
    3. 将实参与形参统一(把实参值赋予形参)
    4. 在函数体里找函数声明,把函数声明也作为AO对象的属性名,值为函数体()

    上面那段代码,fn函数执行之前,先发生预编译过程

    第一步

    AO = { }

    第二步

    AO = {
          a:undefined,
          b:undefined
    }

    第三步

    AO = {
          a:1,
          b:undefined
    }

    第四步

    AO = {
          a:function (){},
          b:undefined,
          d:function (){}
    }

    第四步代表预编译完成,然后函数执行

    AO = {
          a:123,
          b:function (){},
          d:function (){}
    }
    function fn (a) {
        console.log(a)            //这时函数未执行,打印function a(){}
        var a = 123;            //此时执行了a=123
        console.log(a)            //打印123
        function a() {}
        console.log(a)            //打印123
        console.log(b);            //此时函数未执行,打印undefined
        var b = function () {} 
        console.log(b);            //此时执行了 b=function(){},打印function(){}
        function d () {}
        console.log(d)            //打印function d(){}}
    }            
    fn(1)

    举几个‘栗子

    //1. 
    function fn(a,b) {
    console.log(a);   //打印1
        c = 0;
        var c;
    console.log(b);   //打印function b() {}
        a = 3;
        b = 2;
        console.log(b);    //打印2
        function b() {};
        function d() {};
        console.log(b)     //打印2
    }
    fn(1);
    //2.
    console.log(bar());      //打印function foo() { //body }
    function bar(a,b) {
        return foo;
        foo = 10;
        function foo(){
              //body
        }
        var foo = 11;
    }
    //3.
    console.log(bar());      //打印11
    function bar(a,b) {
        foo = 10;
        function foo(){
            //body
        }
        var foo = 11;
        return foo;
       }

    以上是单个函数发生的预编译和函数执行过程,那么在<script></script>整个脚本中,是怎么样的呢?

    <script type="text/javascript">
      var a = 1;
      function b () {
      var x = 3;
      function d () {}
      }
      var c = function () {
        var y = 4;
      }
    </script>

    同样的过程,在语法分析之后,开始预编译,不过此时预编译创建的叫GO对象,(Global Object)

    GO/window = {
    a:undefined,
    c:undefined,
    b:function b () {
          var x = 3;
          function d () {}
              }
    }

    函数执行:

    GO/window = {
    a: 1,
    c: function () {  var y = 4;  },
    b: function b () {
    var x = 3;
    function d () {}
                }
    }

    在执行b函数之前,将b函数预编译,也就是创建b函数的AO对象
    如果有两个<script></script>呢?那就先执行完一个,再执行下一个。

    注意问题:
    预编译只有变量声明、函数声明,并不会发生赋值,赋值发生在执行阶段
    匿名函数function (){ } 不参与预编译

  • 相关阅读:
    Difference between 2>&-, 2>/dev/null, |&, &>/dev/null and >/dev/null 2>&1
    (OK)(OK) docker-(centos-quagga-ospf-mdr)--NS3--MANET
    How to Interactively Create a Docker Container
    (OK)(www.nrl.navy.mil) OSPF MANET Designated Routers (OSPF-MDR) Implementation
    docker-batman
    (OK)(OK) NS3
    quagga-mtr——Multi-Topology Routing support for quagga routing suite
    (OK)(OK) seem-tools-CLI-manual.sh
    (OK)(OK) seem-tools-CLI-semi-auto.sh
    (OK)(OK) manet-seem-template.cc
  • 原文地址:https://www.cnblogs.com/jiahuasir/p/10571349.html
Copyright © 2020-2023  润新知