js的词法分析

JavaScript代码运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤:

分析参数
再分析变量的声明
分析函数声明
具体步骤如下:

函数在运行的瞬间,生成一个活动对象(Active Object),简称AO
第一步:分析参数:
函数接收形式参数,添加到AO的属性,并且这个时候值为undefine,即AO.age=undefine
接收实参,添加到AO的属性,覆盖之前的undefine
第二步:分析变量声明:如var age;或var age=18;
如果上一步分析参数中AO还没有age属性,则添加AO属性为undefine,即AO.age=undefine
如果AO上面已经有age属性了,则不作任何修改
第三步:分析函数的声明:
如果有function age(){}把函数赋给AO.age ,覆盖上一步分析的值

例子1

 1 function func(age) {
 2     console.log(age);
 3     var age = 25;
 4     console.log(age);
 5     function age() {
 6     }
 7     console.log(age);
 8 
 9 }
10 func(18);

词法分析:

第一步,分析函数参数:
  形式参数:AO.age = undefined
  实参:AO.age = 18
第二步,分析局部变量:
  第3行代码有var age,但此时第一步中已有AO.age = 18,故不做任何改变
  即AO.age = 18
第三步,分析函数声明:
  第5行代码有函数age,则将function age(){}付给AO.age,即AO.age = function age() {}

所以,执行代码时:

  第2行代码运行时拿到的age是词法分析后的AO.age,结果是:function age() {};

  第3行代码:25赋给age,此时age=25;

  第4行代码运行时age已被赋值为25,结果25;

  第5,6行代码是一个函数表达式,所以不会做任何操作;

  第7行代码运行时age仍然是25,结果也是25。看看浏览器执行的结果,bingo~~
  答案:function age{}; 25 ; 25;

例子2

1 function func(age) {
 2     var age;
 3     console.log(age);
 4     var age = 25;
 5     console.log(age);
 6     function age() {
 7         console.log(age);
 8     }
 9     age();
10     console.log(age);
11 
12 }
13 func(18);

答案:function age(){console.log(age)} ; 25 ; age is not a function

例子3

 1 function func(age) {
 2     var age;
 3     console.log(age);
 4     function age() {
 5         console.log(age);
 6     }
 7     age();
 8     console.log(age);
 9 
10 }
11 func(18);

答案:3个function age(){}

例子4

1 function func(age) {
2     console.log(age);
3     var age = function age() {
4         console.log(age);
5     };
6     age();
7     console.log(age);
8 }
9 func(18);

答案:18 ;function age(){ console.log(age)} ;function age(){console.log(age)}
【注意】: function age() {console.log(age);} 内部的console.log中的age找不到age,就向上找,发现age就是方法

例子5

function a(b){
    alert(b);
    b = function (){
         alert(b);
    }
    b();
}
a(1);

答案: 1; function(){alert(b);}
【注】:这里要注意的是,b=function(){alert(b);}是一个赋值过程,发生在执行过程中,不是分析过程,
同时 function() {alert(b);} 内部的b找不到b,就向上找,发现b就是方法

所以:
方法一:function t1(){}
方法二:t1 = function(){}
这两种方法效果完全不同,方法一是声明函数t1()发生在词法分析过程中,方法二是函数赋值发生在执行过程中

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

这是jquery最外层的代码,(function(window,undefined){})内层表达式,返回值是函数,包在小括号里,当成表达式来执行

后面紧跟着一个小括号(function(window,undefined){})(window),这就是立即调用,内层函数没有起名字,就是匿名函数,不污染全局变量,立即执行,称为立即执行匿名函数表达式

问题:(function(window,undefined){})(window) 为什么传window,而又不会传undefined?
答:
1、传window是为了速度
例如一个函数:

function(){
    function(){
        function(){
            function(){
                document.get........ //这个document会沿着作用域层层上涨,知道最外层,就慢
            }
        }
    }
}

,所以jquery就为了加快内部查找变量的速度,才直接将window以参数形式传进来,这样window就在jquery的AO上,那查找速度肯定快。

2、不传undefined是为了安全,在ie、火狐低版本中,undefined竟然可以重新赋值,如:undefined=3,
声明undefined局部变量(名字是undefined而已),同时又不传参,值自然是undefined,防止外界对undefined这个值造成污染

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值