zoukankan      html  css  js  c++  java
  • JS预解析机制

    JS的预解析过程:

    1,预解析

    2,再逐行解读代码,

    实例:
    ----------------------------
    <script>
    var name="xm";
    var age=18;
    function fn(argument){
    console.log(name);//输出未定义:undefined
    var name="xh";
    var age=12;
    }
    </script>
    ----------------------------
    解析:

    全局作用域,局部作用域,都是通过以下两个步骤进行预解析的。

    1,先读取有var 的变量(没有使用var的变量是不会被预解析的),给赋值为:undefined。如果两个变量重名,并不影响预解析的过程,就写一个变量就行,因为都将变量赋值为undefined(在逐行读取时,只是不同的赋值而已。),如果有函数名和变量重名,那就直接去掉变量,不进行解析。如果函数中存在参数,那么参数也一样使用var进行解析。如:var argument=undefined;

    2,再读取function后面的函数---fn,如果有多个函数名重复,那么取最后面一个函数进行声明。

    上面实例有两个作用域,一个是window变量对象的全局作用域,一个是fn变量对象的局部作用域。

    预解析过程如下:

    1,window:

      var name=undefined;

      var age=undefined;

      function fn(argument){
    console.log(name);
    var name="xh";
    var age=12;
    }

    2,fn:

      var name=undefined;

      var age=undefined;

      var argument=undefined;

    预解析就完成了。然后就是逐行解读代码。

    通过逐行解读代码进行赋值,改变变量属性值。如果遇到函数,那么就直接跳过,因为预解析时已经声明过。

    所以,上面实例:console.log(name); 输出为: undefined。

    实例1:

    <script>
    console.log(fn);
    function fn(){}; //预解析:function fn(){};
    </script>

    输出结果:function fn(){};

    实例2:
    <script>
    console.log(fn);
      var fn=function(){}; //预解析:var fn=undefined;
    </script>

    输出结果:undefined 未定义。

    实例3:
    <script>
    console.log(a);//所以这里a是没有定义,运行就报错。运行未定义变量报错,运行未定义属性返回undefined
       a=1;//预解析没有变量。
    </script>
    输出结果:这里的a没有定义,所以报错,未定义。
    -----------------------
    <script>
    console.log(a); //预解析中只剩下一个函数a,所以这里输出是整个函数a。 函数里面的表达式不进行预解析
    var a=1; //声明一个变量 a 进行赋值,所以跟预解析没关系
    console.log(a);//所以这里输出为:1。
    function a(){ //两个函数重名只保留最后一个,所以这个函数不进行解析,在逐行解读代码时,没有进行解析的代码也是跳过的。
    console.log(2);
    };
    console.log(a);//函数被当成变量赋值为:1,a就是一个变量。所以这里输出为:1。
    var a=3; //声明一个变量 a 进行赋值,所以跟预解析没关系
    console.log(a);//这里输出为:3。
    function a(){ //被预解析的函数就直接跳过不进行解析,因为预解析时,已经声明过了。
    console.log(4);
    };
    console.log(a);//函数被当成变量赋值为:3。所以这里输出为:3。
    a(); //函数被当成变量赋值为:3。所以这里的a为变量,变量不可以当做函数执行。
    </script>

    输出结果:
    function a(){console.log(4);}

    1

    1

    3

    3

    报错(a=3,不能当函数执行);

    预解析:
    //var a=undefined; 变量a与函数 a 重名,所以变量不进行预解析。
    //两个函数重名,只对最后一个进行预解析。
    function a(){
      console.log(4);
    }
    -----------------------
    预解析是一个标签执行完毕并且逐行解读代码完成,才执行第二个标签的预解析和逐行代码解读:
    以下是存在两个script的情况,进行预解析:
    <script>
    console.log(a);//这个标签预解析后没有变量需要声明,再执行console.log(a); a是没有声明的变量,所以报错。
    </script>
    <script>
    var a=1;
    </script>
    输出结果为:报错。第一个标签的a没有声明。
    预解析是一个标签执行完毕并且逐行解读代码完成,才执行第二个标签的预解析和逐行代码解读:
    以下是存在两个script的情况,进行预解析:
    <script>
    var a=1;//预解析:var a=undefined; 再被复制为1。执行完毕,再进行下面一个标签预解析,在逐行解读代码。
    </script>
    <script>
    console.log(a); //所以这里输出为:1。
    </script>

    输出结果:1。
    -----------------------
    <script>
    var a=1; //解析:var a=undefined;
    function fn(a){ //解析:var a=undefined;
    console.log(a); //执行完fn(a)后,输出1。因为这里的a变成全局变量了。重点。
    a=2;
    }
    fn(a); //这里的a是全局变量,因为局部变量不能再全局中使用,只有全局变量才能在局部中使用。所以这个a=1。
    console.log(a); //局部变量不能再全局中使用,只有全局变量才能在局部中使用。所以这里输出1。
    </script>

    输出为:1 , 1

    预解析:
    window变量对象的属性以及方法:
      var a=undefined;
      fn(a){console.log(a); a=2;};

    fn变量对象的属性以及方法:
    var a=undefined //这里的 a 是参数。
    ------------------------
    不要在代码块中声明函数,因为这样有些老的狐火浏览器无法进行正确的预解析。
    if(){
      function fn_name(argument){.....body......}
    }
    for(){
      function fn_name(){.....body......}
    }

     =================总结=====================

    上图:

    基本变量复制(这里应该是赋值)时,创建一个副本:

    var name="xm";

       name="xh";//基本类型赋值,跟上面一个值无关。即:两个值,在栈内存中开辟了两个位置存放数据。

    引用类型赋值的其实是指针:

    var xh={sex:"female" age:18};

    var xm=xh;//把xh的引用赋值给xm。还是指向同一个堆内存空间,所以两个值和类型都想相等(即同一个引用),即相等。

    基本数据类型和引用数据类型传递参数。

    两种类型都一样:都是按值传递参数,并不是按引用传递参数。直接值代替参数。

     

  • 相关阅读:
    【题解】 bzoj2748 [HAOI2012]音量调节 (动态规划)
    【题解】 bzoj1190: [HNOI2007]梦幻岛宝珠 (动态规划)
    【题解】 bzoj1864: [Zjoi2006]三色二叉树 (动态规划)
    【题解】 [ZJOI2006]书架 (Splay)
    【题解】 [HNOI2004]宠物收养场(Splay)
    【题解】 [HNOI2002]营业额统计 (Splay)
    【题解】 [ZJOI2008] 泡泡堂(贪心/二分图/动态规划)
    【题解】 [SDOI2009] Elaxia的路线(最短路+拓扑排序)
    Aptana Studio 3 如何汉化,实现简体中文版
    js中获得当前时间是年份和月份
  • 原文地址:https://www.cnblogs.com/Knowledge-is-infinite/p/10623172.html
Copyright © 2011-2022 走看看