JS运行三部曲(预编译)

本文介绍了JS运行的三个步骤,即语法分析、预编译和解释执行。重点阐述了预编译,它是在函数执行前在内存中为变量和函数申请空间。详细说明了预编译过程,包括创建AO或GO对象、处理形参和变量声明等。还提及了函数执行和多脚本执行情况,以及预编译的注意事项。

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 (){ } 不参与预编译

转载于:https://www.cnblogs.com/jiahuasir/p/10571349.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值