javascript函数预编译四部曲

深刻理解JS中的“预编译阶段”和“执行阶段”

什么是“预编译”

1、javascript是一种解释型语言,例如C、Java等强类型语言中的编译阶段,

   它是没有这个步骤的,因此,javascript中有了类似于强类型语言编译阶段的步骤---预编译,

   同时,我们需要知道,js引擎不是逐行的解释代码,而是按照代码块解释,

   即,以<script></script>标签为块,进行解释,

   另外,我们还需要知道的是,预编译过程是在执行过程的前一刻发生并执行完毕,

   也就是说到了执行阶段的时候,预编译的过程已经完成了;

2、我们在编程过程中有自己的一套语言和语法,同样的,计算机也有自己的一套,

   面对代码,我们可以清晰的知道它的运行方式和顺序,但是,计算机不一定能懂,

   因此,预编译也是让计算机“认识”我们所写的代码的过程,

   例如下文将会提到的,AO对象,就是JS引擎在执行代码过程中重要的依赖;

javascript中的声明方式

在js中声明的方式有两种,变量声明和函数声明

即,var(let、const)和function

了解这个对下面预编译的过程有重要帮助

下面随着代码分析预编译的过程

  <script>

    function test(a) {

      console.log(a);

      var a = 123;
      
      console.log(a);

      function a() {

      };

      console.log(a);

      var b = function () {

      };
      
      console.log(b);

      function d() {

      };
    }

    test(1);

  </script>


    先自己尝试着写出这段代码执行后的结果是什么?

函数预编译发生在函数执行的前一刻

第一步 创建AO对象

AO对象:官方翻译为执行期上下文

在上述代码中,script标签内,简单的看,有一个函数的定义及该函数的传参执行两个步骤,

js引擎扫描完代码,在 “test(1)”这行代码将要执行的前一刻,开始了“预编译”的过程,

创建js引擎所认识的AO对象,该对象中存放着变量和方法的声明,仅供js引擎进行读取等操作,

每个函数都会有自己的AO对象,此时这个对象是属于test这个函数的,

也就是说这个AO对象就是test函数的作用域

AO {

}

第二步 找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined

形参为a,作为键添加到AO对象中,值为undefined;

变量声明有两个,var a;var b;

注意,由于声明的变量a和形参相同,那么只需要添加一次就可以了,

那么AO对象就变为如下:

AO {
  a:undefined,
  b:undefined
}

注意:
1、相同的变量名作为一次属性名
2、变量声明,不是函数声明

第三步 将实参值和形参统一

test(1) ===>  实参为1,将1赋值给AO对象中的属性a

AO {
  a:1,
  b:undefined
}

第四步 在该函数体里面找函数声明,值为函数体

函数声明有两个

function a() {}

function d() {}

其中a函数声明的函数名与变量声明中的变量名相同,在此步骤中,函数声明优先级高于变量声明,

将会覆盖之前的变量声明,同时,添加d的函数声明,

此时AO对象变为:

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

注意:
function xxx() {} 为函数声明
var xxx = function () {} 是函数表达式,是变量声明,不是函数声明,

到此时,预编译的过程完成,下面是函数执行过程

1、第2行执行console.log(a);

此时从AO对象中可以知道,a的值为 function a() {}

故,第2行代码执行的结果为 fucntion a() {}

2、代码继续执行,第5行

var a = 123; 执行完该行代码之后AO对象变为

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

故,第7行代码执行的结果为 123

3、9-11行代码为函数声明

在预编译过程的时候已将其提升,AO对象不变

故,第13行代码执行的结果为 123

4、执行到15-17行代码

变量b在预编译过程仅仅提升声明,并没有对其赋值,此时对变量b进行赋值

AO对象变为:

AO {
  a: 123,
  b: function () {},
  d: function d() {}
}

故,第19行代码执行的结果为 function () {}

5、21-23行代码在预编译过程时候处理过,至此,函数执行完毕

上述代码执行的结果为

function a() {}
123
123
function () {}
练习题

  function fn(a, b) {
    console.log(a);

    console.log(b);
    
    var b = 234;

    console.log(b);

    a = 123;

    console.log(a);

    function a() {

    };

    var a;

    var b = function () {

    }

    console.log(a);

    console.log(b);
  }

  fn(1);
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值