JAVASCRIPT之词法分析----你真的懂JS吗? 【未完待续】

来源:互联网 发布:网络管理的基本概念 编辑:程序博客网 时间:2024/06/16 05:11

先上几道题: 

1、

<script>     alert(a);</script>

<script>     alert(a);     var a = 1;</script>

2、

<script>         if("a"  in window){     var a = 1; } alert(a);</script>


3、

<script>  function t(g){     alert(g);   function g(){    alert(1); }  }     t(2);  </script>

4、

<script>  function t(t){      alert(t);      t();  }     t(function(){      alert(t);  });  </script>

5、在不同浏览器上看看效果
<script>  var t = function a(){      alert(a);  }    t();  alert(a);  </script>

    谁能做到只分析代码就得出正确结论,并且说明原理, 那么恭喜你,说明你深刻掌握了词法分析的原理。 


    这五道题的结果可能让很多人感觉到意外,JS虽说是脚本语言, 但是它在执行之前会先做预解析, 也就是词法分析。

    词法分析分成三个步骤:

      1、检查var声明,

           当一段程序或函数在运行前,会为当前作用域创建一个活动对象AO,   检查所有用var声明的变量, 将此变量挂到该AO上,但并不赋值(变量的赋值是发生在代码真正运行时);

      2. 函数参数传递,

           若这段程序是个函数,JS引擎会将传递的参数赋值给该函数的形参。 

      3、函数声明

           检查当前域中的函数声明,将声明的函数挂到AO上。这样就可以形成一个AO链, 函数声明的形式为:function aa(){} ,

     

    现在我们再来分析这五道题 。 

    1, 第一道题中第1小题报错。因为使用了一个未声明的变量。第2小题为undefined,在词法分析中,当前活动对象已有变量a, 只是没有赋值。 所以为undefined.

    2、 第二题是想判断a是否为window的属性, 如果是,则a=1, 可是JS引擎会先检查var声明,将a挂到AO上, 然后再运行。 导致代码在运行时, a已经声明, a=1. 

    3、 第三题当函数t在运行前, 词法分析先检查有没有var声明,没有, 再到参数传递, 将g挂到t的活动对象AO上,并将其赋值为2, 再去检查是否有函数声明, 正好有一个函数名为g的函数声明,先判断AO上是否有g这个变量,如果没有,则创建,没有则覆盖,那么g变成了一个函数。 值为function g(){  alert(1) };

    4、第四题有点绕,需要我们了解作用域的概念, 让我们来一起分析下。 当代码在运行前, 首先在window上创建一个AO。将函数t挂到window的AO上。当代码调用函数t时,需要对函数t进行词法分析了,将传过来的参数function(){alert(t)} 传递给参数t, 那么alert(t)得到的结果自然是function(){alert(t)}  ,可t()为何却得到

         function t(t){

              alert(t);

              t();

        }

       匿名函数function () {   alert(t);  } 是在哪里定义的, 是在最外层的window上。  此匿名函数用到了变量t, 在该匿名函数中找不到变量t,那么就会往它的上一级去找。它的上一级是谁, 是window而不是运行时的t, window上正好有个变量为t.

       如下图:   

             

      这个例子也正说明: 变量的值取决于声明时的环境而不是运行时的环境,这是与其它语言最大的不同。 

      如还不理解,可以再看看这题:

<script>  var a = 1;  function t(g){     var a = 2;       g();  }  t(function(){     alert(a);  })   </script>

    5、第五题,函数表达式

0 0
原创粉丝点击