Javascript“预编译”理解

来源:互联网 发布:法律盈余 知乎 编辑:程序博客网 时间:2024/05/23 16:57

      首先来看一个例子:

<script type="text/javascript">    var a = 1;    function show() {       console.log(a + 1);       var a = 2;       console.log(a + 1);    }    show();</script>

      其输出结果为:NaN, 3

      为什么第一个打印出来的结果是NaN,而不是2呢?

      事实上,JS的解析过程分为两个阶段:预编译期(预处理)与执行期。

      预编译时JS会对本代码块中所有声明的var变量和函数进行处理,变量会被初始化为undefined,函数则在预编译时就会被解析。
      注: 一个script标签即为一个代码块

      所以上面一段代码的执行过程是:

      1.第一步扫描全局var关键字:

var a;  //这个a为全局变量,被初始化为undefined

      如果是函数表达式,如var b = function(){},那么b也会被初始化为undefined,等号右边的函数并不会被赋值给b,也不会被解析。

      2.第二步扫描function,函数被解析过程如下:

function show() {    var a;                 //局部变量a被初始化为undefined    console.log(a + 1);    //这里引用的是局部变量a,值为undefined,与全局变量a没有半毛钱关系    a = 2;                 //局部变量a被赋值为2    console.log(a + 1);    //2+1}

      3.第三步按顺序执行代码,最终如下:

var a;                     //全局变量a,被初始化为undefinedfunction show() {    var a;                 //局部变量a被初始化为undefined    console.log(a + 1);    //这里的a引用的是局部变量,值为undefined    a = 2;                 //局部变量a被赋值为2    console.log(a + 1);    //2+1}a = 1;                     //全局变量a,被赋值为1,不会影响局部变量a的值show();                    //执行show函数

      当undefined与number运算时,由于undefined不是number类型,则undefined会被转化为NaN,NaN与number运算时,结果则为NaN。所以第一个打印结果为NaN,第二个打印结果为3。

      而如果show函数里没有声明变量a,那么show函数里的a会沿着作用域向上查找,此时a为全局变量,例子如下:

var a = 1;function show(){    console.log(a + 1);}show();

      其预编译后为:

var a;                   //a为全部变量,开始为undefinedfunction show(){    console.log(a + 1);  //引用全局变量a,值为undefined}

      按顺序执行时

a = 1;    //--全局变量a的值改变,被赋值为1,则show函数里引用全局变量a也变为1.show();   //--执行console.log(a + 1),此时的a值已变为1

      所以其打印出来的结果是2。

      小结一下:JS 在执行前会进行类似”预编译”的操作,而且先预定义变量再预定义函数。而无论是声明的变量还是声明式函数,在执行的时候,都可以覆盖预编译时期的值。这个过程如果发现语法错误,预解析终止。

0 0