function abcd(){ console.log(aa); //undefined console.log(aa); //not defined(报错!!) var aa=bb=cc=dd=0; console.log(aa); //0 } abcd();
声明:本文只是自己的感悟,学习原址:http://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html 汤姆大叔写的真心不错,赞一下
这里我要说的是,我之前在大叔的博客上看的有些绕的地方,比如:
function b (a){ console.log(a);//function a(){alert(1);} var a=4; var a; var a=function(){ alert(3); } a=2; function a(){ alert(1); } return a; } console.log(b(0)); //2
这样一个例子,为什么显示的先是function然后是2,可能很多人都知道,在代码解析的时候,function定义的函数就会存在,var需要在执行的时候变量才会有值,但是具体的实现是什么?因为即使我们还没有执行函数,访问var的变量也不会报错,这就说明这个变量是已经定义的了(可以自己试试哦)
其实这里要提到执行环境的作用了,每个函数都有自己的执行环境(也翻译为:执行上下文,个人觉得执行环境稍微好听一点),而处理执行环境(就是变量会变化的时候)会有2个阶段,
1:进入执行环境(函数声明的时候)
2:执行代码(函数执行的时候)
另一个我们需要注意的东西是,在函数内部有几种变量,这里的分类标准并不是变量类型,而是执行环境对变量处理方式
1:var 声明变量(例子中的 var a;) 2:function声明(例子中的function a(){}) 3:直接访问形式参数(例子中的a;)
在函数声明阶段:
1:function声明如果和其他2类声明同名的话,会把其他2类的声明覆盖
2:var声明不会影响到同名形式参数(注意这里只有声明,没有赋值),将会是undefined(实际上就算影响了,也是undefined,因为没有赋值)
所以:我们在代码刚开始执行的时候,a的值就是那个function
在函数执行阶段
代码执行的时候依旧是遵循上面的规则,var如果是同名的声明不会影响到,但是一旦赋值的话就直接导致OA内这个属性的值变为新值(注意,在AO内一个名字只能作为一个属性),话句话说,在代码执行的时候就只有赋值才能影响变量值
这里再举一个比较简单的例子:
function abcd(){ console.log(aa); //undefined console.log(bb); //not defined(报错!!) var aa=bb=cc=dd=0; console.log(aa); //0 } abcd();
在这里的bb不会和aa一样显示undefined,因为bb是not defined状态,aa是定义了,值为undefined,根据我们之前讲到的,因为在执行abcd()这个函数的时候,var会首先定义变量,但是赋值需要到执行var语句的时候。所以我们可以先访问aa,但是却不能访问bb,因为没有bb这个变量,
bb会在赋值阶段自动生成一个全局属性,window.bb,这个时候再给bb赋值。所以,在函数外部,可以访问bb却不能访问aa(报错),也是因为aa只是在函数内部定义的变量,而bb是全局属性