浅谈js预编译

JS的两大特点

1,单线程语言,什么是单线程,就是说JS同一时间只能做一件事,即使是HTML5中提出JS可以创建多个线程,但是还是要受主线程控制,并且不能操作DOM。所以本质上来说,JS还是单线程语言。
2,解释性语言,即翻译一句执行一句,但又不是真的这么直接。

     console.log(a) // undefined
     console.log(b) // 报错
     var a = 10;

我们发现a是undefined而b直接报错,从这里我们可以看到JS不是单纯意义上的翻译一句执行一句,要不然a应该会直接报错,下面的不执行。其实JS执行分三步。

1,语法分析 通篇扫描看看有没有低级错误(少写大括号,中文标点什么的)。

2,预编译

3,解释执行 解释一行执行一行。

现在我们要理解的就是其中的预编译环节,要了解预编译首先要知道一个词global (全局变量)。
1,一切未经声明的赋值,就为全局对象(window)所有。

    function text(){
       b = 10;
    }
    text();
    console.log(window.b) // 10

2,在全局范围声明的全局变量都是全局属性。

    var a = 12;
    console.log(window.a) // 12

好了先看一下预编译的步骤预编译分为函数预编译和全局预编译,咱们先看一下函数的,然后全局预编译就简简单单了。
函数预编译四部曲:

  1. 创建AO对象 Activation Object;(执行期上下文) ;
  2. 找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined ;
  3. 将实参值和形参统一;
  4. 在函数体里找函数声明,值为其函数体。

直接写出来看的不是很明白,可以通过JS题来验证

   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(){}
        }
        fn(1);

看到这道题先别慌,按照步骤一步一步来。
1,创建AO对象 Activation Object (执行期上下文)

  AO{ }

2,找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined ;
从上往下的找形参和变量声明,为他们赋值undefined,遇到同名的下面的覆盖上面的。

      AO{
            a : undefined,
            b : undefined,
            d :  undefined
        }
  1. 将实参值和形参统一; 发现a的实参是1
      AO{
            a : 1,
            b : undefined,
            d :  undefined
        }
  1. 在函数体里找函数声明,值为其函数体。a和d是函数声明,为他们赋值函数体,b是函数表达式,所以不进行这一步。
     AO{
           a : function a(){},
           b : undefined,
           d :   function d(){}
       }

这下就是预编译完成了,预编译在函数执行的前一刻,所以预编译刚完成,函数就开始执行。

   function fn(a){
           console.log(a);  //function a (){}     打印a函数上哪找a在自己的AO对象了,发现a是函数体,于是打印函数体

           var a = 123;

           console.log(a);  // 123     这里预编译看的是有一个b变量后面的没看,所以看到后面的123,就为a赋值123

           function a(){}

           console.log(a);  // 123     这里因为预编译已经看过这a函数了,所以执行的时候就不会再看了

           console.log(b) ; // undefined    这里看AO里有b就打印undefined

           var b = function (){}

           console.log(b); // function(){}            这里预编译看的是有一个b变量后面的没看,所以执行的时候看到后面的函数体,为b赋值函数体。
           function d(){}

        }
        fn(1)

好了基本函数的预编译这样就差不多了,还有一个就是函数在自己AO对象找不到变量的时候,会在全局对象GO即window中找,都找不到就会报错。

全局预编译三部曲

  1. 创建GO对象:执行期上下文(Global Object) GO === window
  2. 寻找变量声明,并且当做属性放在GO对象里,值为undefined
  3. 寻找函数声明,值赋予函数体
   console.log(a) // undefined   在全局GO{a;undefined,text:function text () {}   }早到a 打印undefined
   function text(){}
   console.log(b) // 报错
   var a = 10;

全局的预编译和函数一样,由于没有参数,还显得更为简单,我就不多赘述了。

然后这个主要是多记多做题,就可以熟练地掌握了。我这里这写几道题,大家可以自己看看。

    function test(a, b) {
            console.log(a);
            console.log(b);
            var b = 234;
            console.log(b);
            a = 123;
            console.log(a);
            function a() { }
            var a;
            b = 234;
            var b = function () { }
            console.log(a);
            console.log(b);
        }
        text(1)
  console.log(test);
        function test() {
            console.log(test);
            var test = 234;
            console.log(test);
            function test() { }
        }
        test(1)
 	    global = 100;
        function fn() {
            console.log(global);
            global = 200;
            console.log(global);
            var global = 300;
        }
        fn();

入职不久的小前端从今以后开始自己的技术分享之旅,欢迎建议和批评。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值