JS学习——函数预编译

                                                     预编译讲解及案例

1.1 预编译前奏

     例子:

        (1) var a = 10;

          console.log(a); -->结果 10

       (2) a = 10;

         console.log(a); -->结果 10

      (3) console.log(a); -->报错,提示说a未定义

1.2 连续赋值

        var a = b = 3;

     在JS中执行顺序为从右到左,因此首先会执行b = 3【此语句说明b为全局变量,归window所有】,而此时b属于未定义状态,因为var 只针对a,该语句的含义是将3赋值给变量b,然后再声明a,将b的值赋给a.

     但是如果执行

         console.log(window.a);-->undefined

         console.log(window.b);-->3

说明变量未经声明就被赋值,该变量归window所有

重点:

(1)变量未经声明就赋值,则属于window

(2)一切声明的全局变量,均是window的属性

     例如在JS初始化时,var a = 23;则window.a-->23;

1.3 预编译四部曲

 1.3.1 案例一

function fn(a){

     console.log(a); ②

      var a = 123; ③

    console.log(a); ④

    function a(){}; ⑤

   console.log(a); ⑥

  var b = function(){}; ⑦

  console.log(b); ⑧

  function d(){}; ⑨

}

   fn(1);

执行函数前一刻会进行预编译操作

讲解:

(1)创建AO【Activation Object】对象,简称为执行期上下文

(2)找出形参和变量声明,并将变量和形参名作为AO对象的属性,值为undefined

(3)将形参和实参进行统一,即将实参传递的值赋给形参名

(4)在函数体里找函数声明,并将值赋予函数体

程序讲解:

根据预编译的执行时间来说,预编译一般都发生在程序执行前一刻,因此该预编译的执行:

(1) 首先会创建一个AO对象

AO{

}

(2) 根据预编译的四部曲

在程序中找出形参和所有的变量声明,并将形参名和变量名作为属性存放到AO对象中,形参为fn(a)中的a,变量声明有:var a;var b;

并且属性名的值为undefined

注意:此处的形参为a,变量名也存在a,但在AO对象中存放时,如有相同的名称,那仅放一次即可。

因此AO对象为:AO{

a : undefined,

b : undefined

}

(3) 实参和形参进行统一,即将实参的值赋给形参

形参为a,实参为1,

因此AO对象为:AO{

a : 1,

b : undefined

}

(4) 查找函数声明,并将函数体赋值给属性

函数声明以function 开头,因此程序中的函数声明有:a,d两种。但由于AO对象中已存在属性a,[a原先的值被新的值所替代]

因此AO对象为:AO{

a : function a(){},

b : undefined,

d: function d(){}

}

上述过程均属于预编译,以下开始执行程序中的语句

(1) 首先执行语句②

将a的值打印,a的值会从预编译所产生的AO对象中去获取

所以语句console.log(a); 执行的结果为:function a(){}

(2) 执行语句③

由于变量的声明提升,var a在预编译时就被执行,所以现在只执行a = 123的语句,AO对象变为:

AO{

a : 123,

b : undefined,

d: function d(){}

}

语句④的执行结果为123

(3) 执行语句⑤

function a(){};属于函数声明,而根据函数声明提升,在预编译时就被执行,所以该语句不再执行

(4) 执行语句⑥

打印a的值,依然会去AO对象中获取值,结果为:123

(5) 执行语句⑦

var b = function(){};

这属于函数表达式,而var b根据变量声明提升,在预编译时已被执行,所以直接将b的值放入到AO对象中

AO{

a : 123,

b : function(){},

d: function d(){}

}

(6) 执行语句⑧

从AO对象中获取b的值:function(){}

(7) 执行语句 ⑨

function d(){};属于函数声明,根据函数声明提升,该语句在预编译时已执行,所以不再执行

最终的AO对象为:

AO{

a : 123,

b : function(){},

d: function d(){}

}

1.3.2 案例二

function test(a,b){

     console.log(a);

      c = 0;

       var c;

      a = 3;

      b = 2;

   console.log(b);

   function b(){};

   function d(){};

   console.log(b);

}

    test(1);

 

一、预编译开始

1、创建AO对象

AO{

}

2、找到形参和变量声明,并将形参名和变量名作为AO对象的属性

并赋值为undefined

AO{

a:undefined,

b:undefined,

c:undefined

}

3、将实参同形参进行统一

AO{

a:1,

b:undefined,

c:undefined

}

4、查找函数声明,并将函数体赋给属性

AO{

a:1,

b:function b(){},

c:undefined,

d:function d(){}

}

预编译完成。

二、开始执行程序

(1) console.log(a);

执行后,会从预编译中创建的对象AO获取值:即a = 1;

(2) c = 0;

AO{

a:1,

b:function b(){},

c:0,

d:function d(){}

}

(2) var c;

变量声明提升,不再执行

(3) a = 3;

AO{

a:3,

b:function b(){},

c:0,

d:function d(){}

}

(4) b = 2;

AO{

a:3,

b:2,

c:0,

d:function d(){}

}

(5) console.log(b);

执行结果为:2

(6) function b(){};

函数声明提升,不再执行

(7) function d(){};

函数声明提升,不再执行

(8) console.log(b);

执行结果为:2

 

1.3.3 案例三

 全局对象window

在预编译中,除了存在AO对象,同时也有GO对象,所谓GO即为

Global Object === window 这是同一个对象的不同名称而已。

function test(){

var a = b = 123;

}

AO{

a : undefined

}

GO{

b : 123

}

GO对象的构成同AO的步骤一样,除了实参和形参进行统一的步骤没有,其他步骤均存在。

 

1.3.4 案例四

全局对象复杂案例

<script>

console.log(test);

function test(test){

console.log(test);

var test = 234;

console.log(test);

function test(){

}

}

test(1);

var test = 123;

</script>

程序讲解:

一、预编译

1、创建GO对象

GO对象>AO对象

2、GO对象的构成,会针对于script中所有的程序而言,不会同AO创建时,仅仅针对于函数内部,因此在全局范围类查找形参和变量声明

GO{

test : undefined

}

3、找到函数声明,并赋值函数体

GO{

test : undefined

}

4、找函数声明,因此全局对象为:

GO{

test : function test(){}

}

预编译完成,开始执行程序

二、程序执行

(1) console.log(test);

执行结果会从GO对象中获取值,结果为

function test(test){

console.log(test);

var test = 234;

console.log(test);

function test(){

}

}

(2) test(1);//去调用以下函数

function test(test){

console.log(test);

var test = 234;

console.log(test);

function test(){

}

}

执行该程序时,会创建AO对象

AO{

}

根据AO对象的预编译四部曲

a、查找形参和变量声明,并将形参名和变量名作为属性,值为

undefined

AO{

test : undefined

}

b、将实参和形参进行统一

AO{

test : 1

}

c、查找函数声明,并赋值函数体

AO{

test : function test(){}

}

编译完成,内部程序执行

a、console.log(test); //function test(){}

b、var test = 234;

AO{

test : 234

}

c、console.log(test);//234

d、function test(){};//预编译已执行,不再执行

因此最终的AO对象为

AO{

test : 234

}

(3) var test = 123;

全局对象为:

GO{

test : 123

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值