zoukankan      html  css  js  c++  java
  • Javascript 笔记与总结(1-2)词法分析

    词法分析,按顺序分析 3 样:

    第 1 步:先分析参数

    第 2 步:再分析变量声明

    第 3 步:再分析函数声明

    一个函数能使用的局部变量,就从上面 3 步分析而来。

    具体步骤:

    0:函数运行前的瞬间,生成 Active Object(活动对象)

    1: 1.1 把函数声明的参数,形成 AO (Active Object)的属性,值全是 undefined,

      1.2 接受实参形成 AO 相应属性的值

    2:分析变量声明,如 var age,如果 AO 上已经有 age 属性,则不作任何影响;如果 AO 上还没有 age 属性,则添加 AO 属性,但此时没赋值,值是 undefined

    3:分析函数声明,如 function foo(){},则把函数赋给 AO.foo 属性

    注:如果此前 foo 属性已经存在,则会被覆盖成函数

    例1

    <script>
        function a(b){
            alert(b);
            function b(){
                alert(b);
            }
            b();
        }
        a(1);
    </script>

    【答案】:两次弹出

    function b(){

    alert(b);

    }

    【分析】

    分析期:

     0. AO = {}

    1.

      1.1 分析参数 AO = {b:undefined}

      1.2 接收参数 AO = {b:1}

    2. 分析 var 声明,此处函数没有 var

    3. 分析函数声明,AO = {b:function(){alert(b);}}

    执行期:

    alert(b);   // function

    b();  // 由作用域寻找到 a 函数中的 b,即 function,alert() 出来

    例2

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

    【分析】

    词法分析过程:

    AO{ age = undefined }

    运行过程:

    t(5); → AO.age = 5; alert(AO.age); //5

    t(); → AO.age = undefined; //AO.age 没有得到赋值,还是 undefined

    例3

    <script>
        function t(age){
            var age = 10;
            alert(age);
        }
        t(5);
    </script>

    弹出 10。

    【分析】

    词法分析过程:

    0. 形成AO = {}

    1.

      1.1 分析形参 AO = {age:undefined}

          1.2 接收形参:AO = {age:5}

    2. 分析 var age,发现 AO 已有 age 属性,不做任何影响

    执行过程:

    AO.age = 10

    alert(age); //10

    例4(和例1 做对比):

    <script>
        function t(greet){
            var greet = 'hello';
            alert(greet);
            function greet(){
            }
            alert(greet);
        }
        t(null);
    </script>

    弹出两次 'hello'

    【分析】

    词法分析过程:

    0. AO = {}

    1. 

      1.1 分析形参:AO = {greet = undefined}  

      1.2 接收形参:AO = {greet:null}

    2. 分析 greet 变量声明,AO 已经有 greet 属性,因此不做任何影响

    3. 分析 greet 函数声明,AO.greet = function(){},被覆盖成函数

    执行过程:

    greet = 'hello';

    alert(greet);

    alert(greet);

    【再分析】

    var greet = 'hello';

    这一句要当成两句看(两次执行):① 分析期的 var 声明过程 ② 运行期的 赋值 过程

    由于在运行期被赋值成了 'hello',因此两次 alert 弹出的都是 'hello'

    如果去掉该句(则和例 1 一样)或者改为 var greet; ,则弹出两次

    function greet(){}

    例5 

    <script>
    function a(b){
        alert(b);
        b = function (){
            alert(b);
        }
        b();
    }
    a(1);
    </script>

    分别弹出 1 和 function (){alert(b)}

    【词法分析过程】:

    0:AO = {}

    1.分析参数 AO = {b:undefined}  → {b:1}

    2.分析 var 声明,没有

    3.分析函数声明,没有

    注:b = function(){alert(b)} ,是一个赋值过程,在执行器才起作用

    【执行过程】:

    alert(b);   //b = 1

    b = function(){

      alert(b);    //往上找,找到b = function(){}

    }

    b(); // funtion

    【函数声明 与 函数表达式】

    函数可以赋值给变量,可以作为参数来传递

    function t1(){
    }

    t2 = function(){
    }

    t1 是函数声明,虽然全局内也得到一个 t1 变量,值是 function;

    t2 只是一个赋值过程,值是右侧的表达式的返回结果,即函数

    因此 t1 和 t2 两种方式在词法分析时,有着本质区别:前者在词法分析阶段就发挥作用,后者在函数运行阶段才发挥作用

    例如:

    (function(window,undefined){
    })(window)

    这是 jQuery 的最外层代码

    【分析】

    (function(window,undefined){})

    这是内层表达式,返回值是函数,包在小括号里,当成表达式来执行

    (function(window,undefined){})(window)

    立即调用

    而内层函数又没有起名字,成为匿名函数

    这种手法,匿名函数,立即执行,不污染全局,称为 立即执行匿名函数表达式

    传 window 是为了速度,不传 undefined 是为了防止外界对 undefined 的污染(在 IE 、FF 低版本中,undefined 可以重新赋值,例如 undefined = 3;)

    【作用域链】

    指函数由内到外,产生的 AO 链

    词法分析时由外至内,分析 AO 链;执行时由内到外,寻找 AO 链

    更多词法作用域文章:JavaScript的词法作用域

  • 相关阅读:
    hdu 5101 Select
    hdu 5100 Chessboard
    cf B. I.O.U.
    cf C. Inna and Dima
    cf B. Inna and Nine
    cf C. Counting Kangaroos is Fun
    Radar Installation 贪心
    spfa模板
    Sequence
    棋盘问题
  • 原文地址:https://www.cnblogs.com/dee0912/p/4396798.html
Copyright © 2011-2022 走看看