转载地址:
http://blog.csdn.net/itzhengmaolin/article/details/54565201
作用域:在一定的范围内,对其进行读、写操作“js解析器”执行的过程至少2步:1、"找一些东西":比如 var 、function、参数2、逐行解读代码例:
alert(a);var a=1;function fn1(){ alert(2);}
解析过程:
1、JS的预解析过程 原则:遇到重名的:只留一个(变量和函数重名了,就只留下函数。无论变量在上还是函数在上,与上下是没关系的,跟有值没值有关系。因为变量=undefined,函数=整个函数块,相比之下有具体值的级别更大)
找到var关键字,然后定义其变量名等于undefined,不会管后面的值(在"JS解析器"执行的过程中,所有的变量都等于未定义) 如:a=undefined
找到function关键字,然后用其函数名等于其整个函数块。(所有的函数,在正式运行代码之前,都提前赋了一个值,这个值为整个函数块) 如:fn1=function fn1(){alert(2);}
2、逐行解读代码过程: 表达式可以修改"预解析"的值。函数的声明不属于表达式,改变不了什么东西这个过程遵循"从上往下,从左往右"的顺序执行。当执行一句完毕后,到仓库中查找是否有这个"东西"(变量、函数等)。如果有则弹出其一开始在仓库的值(使用alert方法)遇到表达式(=+ - * / % ++ -- ! 参数……等即能改变值的东西)简单来说,找var 、function、参数,并将变量赋值为undefined、函数名=整个函数,然后将他们存储在仓库中,在进行逐行解读代码的时候,在仓库中提取或修改
练习:
解析过程
1、找关键字(var、function、参数)找到37行的"var a",执行过程:a=undefined找到39行的"function a(){alert(2);}",执行过程:a=function a(){alert(2);}因为仓库里有重名的a,所以要比较优先级,值为函数的大于值为未定义,所以执行过程为a=function a(){alert(2);}找到41行的"var a ",执行过程:a=undefined因为仓库里有重名的a,所以要比较优先级,值为函数的大于值为未定义,所以执行过程为a=function a(){alert(2);}找到43行的"function (){alert(4);}",执行过程:a=function (){alert(4);}因为仓库里有重名的a,所以要比较优先级,值同为函数则比较先后,后面的覆盖前面的,所以执行过程为a=function a(){alert(4);}2、逐行解析:从上往下,从左到右依次执行代码。从36行开始,a的一开始值为function a(){alert(4);}执行37行时,修改仓库中a的值,则变为1执行39行时,并不影响a的值,所以a的值还是1后面亦是如此
一个页面两个script标签,浏览器遇到script标签会用"js解析器"来解析,只有解析完第一个script标签的内容后在执行下一个script标签内的内容,所以下面alert(a); 会报错 a is no defined。
这就是当引用别人写的jQuery库时,在对其修改
var a = 1;
function fn1()
{
alert(a); //undefined var a = 2;
}
fn1();
alert(a);
//1解析过程:
1、预解析:a=undefined;fn1=function fn1(){ alert(a); var a = 2;}
2、逐行解析;a=1遇到函数调用fn1() --函数也是一个局部的域,只要是一个域就会发生预解析和逐行解读代码。相当于其有一个小的仓库。可以理解为1个大仓库包含着1个小仓库,大仓库里的a和小仓库里的a是不同的世界,互不影响。函数调用属于表达式 函数里的预解析: a=undefined; //这里的a是局部的,外面的是全局的,两者没关系 函数里的逐行解析: 执行函数里的alert(a); 先找局部仓库里的a,所以弹出undefined 在执行函数里的var a=2; 所以局部里的a=2,并没有影响全局中的a=1 函数执行完毕后会有垃圾回收机制等
函数调用完毕后,继续全局的逐行解析
var a = 1;function fn1(){alert(a); // 1a = 2;
//注意这里没用var声明}fn1();alert(a); // 2函数里的预解析过程为空,执行函数里的逐行解析代码:当执行到alert(a);没找到a,会顺着函数的作用域跳到上一级(从子级作用域返回到父级作用域的过程叫作用域链,由里到外找)。执行到"a=2"时,发现小仓库里没有a,则由里到外找,找到其父级有a,则修改a的值为2
所以,加var与不加var的区别体现出来了。不加var,会修改全局变量的值
var a = 1;function fn1(a){alert(a); // undefineda = 2;}fn1();alert(a); // 1
参数本质就是一个局部变量。跟上面的其中一种情况(如下)很类似函数预解析时没有发现var、function ,却发现了参数,所以a=undefined。然后逐行解读代码,当读到"alert(a);",执行结果为undefined当读到"a=2;",它会就近找小仓库里有没有a,执行结果为a=2,全局的a还是1不影响