JavaScript预编译(全局)

知识点预习:

1、任何未经声明就赋值的变量,都是全局变量

2、预编译过程中,只是对函数声明的整体提升,对于函数体里边的具体内容,不会进行查看。函数执行的时候,才会去看函数里的具体内容

全局下的预编译,和函数里的预编译,都差不多,如果对于函数执行时的预编译理解的很透彻(可以看上一篇博文:JavaScript预编译-函数),那么对于全局下的编译就很好理解了。

一、预编译

 

1、预编译三部曲

1、创建GO对象:执行期上下文(Global Object)

2、寻找变量声明,并且当做属性放在GO对象里,值为undefined

3、寻找函数声明,值赋予函数体

2、实例讲解

        g=1;
        function demo(){
            console.log(g);//undefined
            g=2;
            console.log(g);//2
            var g=3;
        }
        function g(){}
        demo();
        var g;
        console.log(g);//1,为什么对打印1,请参照JavaScript预编译--函数中的详细讲解

/*GO中对象值的变化情况

GO{

     g:undefined-->function g(){.....},

     demo:function(){....}

}



*/

1、创建GO对象:执行期上下文(Global Object)

GO{

}

2、寻找变量声明,并且当做属性放在GO对象里,值为undefined

GO{

     g:undefined,

     demo:function(){....}

}

3、寻找函数声明,值赋予函数体

GO{

     g:function g(){.....},

     demo:function(){....}

}

4、预编译结束的时候,AO里存储的对象就是如下,在语句的时候,再根据语句情况,修改相应的变量值

GO{

     g:function g(){.....},

     demo:function(){....}

}

5、全局下的预编译,和函数的预编译处理过程一样,只要严格按照预编译的过程来分析,对于变量的处理,就不会出错,其实,我们可以把全局(script标签里的语句)看成是一个大的函数,只是这个函数没有形参,这样结合函数的预编译过程,就不难理解了。

 

二、全局变量

 

上一篇博文,留下了一个小小的知识点没有讲解,就是任何未经声明就赋值的变量,都是全局变量,接下来将通过例子,进行详细讲解

 

1、

function demo(){
    a=123;
}
demo();
console.log(a)//123

在全局预编译过程中,不会对a进行处理,在demo函数执行之前的预编译过程中,因为任何未经声明的变量直接赋值,都是全局变量,所以,a不会出现函数demo的AO中,而是将a放在全局的GO中。所以,在全局打印a的时候,结果是123;

2、



function demo(){
    console.log(b);//undefined
    if(a){
        var b=20;//函数demo的AO中并没有变量a的定义,所以会向上GO中寻找,此时GO中的a为undefined,所以b赋值语句并不会执行
     }
      console.log(b);//undefined
    c=30;//c的前边并没有var,也就是说,c是未经声明的变量,demo预编译的时候并不会处理c,而是在执行c=30语句的时候,将c放在全局的GO中
    console.log(c); //30
}
var a;
demo();
a=10;
console.log(c);//30

上面的情况,严格遵守预编译的执行过程,就不难分析出结果,注意一点:函数demo在预编译的过程中,也会将if语句中的var b提升到AO中,只要不是demo里的函数,都会进行变量声明提升和函数声明的整体提升。

三、易错点分析

在写这篇博文的时候,自己也遇见了一小问题,就是未经声明直接赋值的变量和函数的声明问题,思考了好一会儿,才搞清楚是为什么。现在写出来,希望大家能够对于预编译,理解的更透彻。不多说,看代码,代码很短,一定要仔细看。

//1

function test(){
    a=5;
    console.log(a);//5
    function a(){}
}
test();
console.log(a);//Uncaught ReferenceError: a is not defined


//2
function test(){
    console.log(a);//Uncaught ReferenceError: a is not defined
    a=5;
    console.log(a);//5
}
test();
console.log(a);//5


//3
function test(){
    console.log(a);//f a(){}
    a=5;
    function a(){}
}
test();
console.log(a);//Uncaught ReferenceError: a is not defined

我们先来分析一下上边三个函数的区别,1和3除了函数test里的console.log(a)的位置不同之外,没有任何区别,2中的test函数中没有a函数的声明。这只是表面上的区别。

三个函数里边都没有变量a的声明,只有赋值语句,先看第1个函数,按照任何未经声明就赋值的变量都是全局变量来理解,a就是全局变量,但是运行的时候,怎么都想不通,为什么在函数外边而且是函数执行之后,再打印输出a,竟然会报错,难道全局GO中没有变量a么,浏览器当然是没有任何问题的,那就是我的理解上出现的偏差,然后我就在函数里边打印a,结果是5,这个不奇怪,因为全局变量在函数里边也可以访问,但是全局却没有a,那就说名a是局部变量。

然后就有了第2个函数,没有了a函数的声明,在全局就能访问到变量a了,不报错了,能打印出5了,那就说明,问题出在a函数的声明上,接下来就有了第3个函数,看了第三个函数的输出结果,终于想明白了为什么在全局访问不到a。

上面分析的情况,函数test在预编译过程中,没有形参也没有var声明的变量,然后寻找函数声明,找到一个a函数,放在AO中。test函数执行的时候,a=5,会覆盖AO中a的值,所以在函数体里打印a的值是5,此时a是局部变量,所以在全局打印的时候,会报错。第三种情况,函数test中并没有任何var声明的变量也没有函数定义,所以AO是空的,函数执行的时候,a为全局变量,被送到了GO中,所以会出现上面三种打印情况。

一定要认真理解函数预编译的过程,理解透彻,这样在分析变量值的时候,就不会出错。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值