Javascript scrope

 

作用域:

顾名思义,就是能发生读写等操作的环境;但是又没这么简单,下面就来仔细撸一撸JS中的作用域。

*浏览器内部有读取JS的某段程序,当一段JS代码在浏览器中读到的时候,简单的来说会发生以下几个步骤:

1)预解析:

在代码解读之前发生,相当于一个"仓库",放一些东西,var、function、参数等,预解析时变量都是未定义的,函数则是整个函数块。当代码在一个环境中执行时,会创建变量对象的一个作用域链。是域就要预解析。

2)解读代码:

代码自上而下,从左往右的执行,读到表达式时,预解析仓库中的东西发生改变。

实例:

 

1

1 alert(a);// 报错
2 a=1;

预解析时由于没有var、function等,所以仓库为空。代码自上而下执行时a未定义报错。

 

 2

 1 alert(a); // function a(){alert(4);}
 2 var a=1;
 3 alert(a); // 1
 4 function a(){
 5     alert(2);
 6 }
 7 alert(a);// 1
 8 var a=3;
 9 alert(a);// 3
10 function a(){
11     alert(4);
12 }
13 alert(a); //3
14 a();// 报错 a() <=> 3(),number is not a function;*/

预解析时遇到重名的,会覆盖。变量与函数,留函数;函数与函数,留后面解析的。最后仓库里面有:a=function a(){alert(4);}函数块。

代码执行读到表达式,仓库内容改变,a变为表达式所赋予的值。然后接着读代码。

*注意:function a(){}是函数声明,没有调用,所以不执行,不会进行赋值操作。

 

 3

1 var a=1;
2 function fn1(){
3     alert(a); // undefined
4     var a=2;
5 }
6 fn1();
7 alert(a); // 1

预解析仓库有:a=undefined、fn1=function fn1(){alert(a);var a=2;}
代码读到fn1()时,调用函数,函数内部发生预解析:
---a=1, fn1=function fn1(){alert(a);var a=2;}
------------undefined
继续执行,弹出undefined。

*注意 :函数内部 var a=2 是局部变量,不影响全局变量。

全局执行环境是最外围的一个执行环境,根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样,在web浏览器中,全局执行 环境被认为是windows对象;每个函数都有自己的执行环境。进到一个新环境,就会进行一次预解析。

 

 4

1 var a=1;
2 function fn1(){
3     alert(a); // 1 子级找不到;向父级找;由里到外; 作用域链
4     a=2; // 全局变量,改变值
5 }
6 fn1();
7 alert(a); // 2

在子级执行环境中找不到变量,会沿着作用域链一级一级向外搜索,找到为止,找不到报错。

*注意:不声明而直接初始化的变量是全局变量,完全不推荐。

 

 5

1 var a=1;
2 function fn1(a){
3     alert(a); // undefined
4     a=2;//改变局部变量
5 }
6 fn1();
7 alert(a); // 1

预解析仓库:a=undefined, fn1=function fn1(a){alert(a);a=2;}
读到fn1()时,调用函数,函数预解析
---a=1, fn1=function fn1(a){alert(a);a=2;}
-----------参数a=undefined
继续执行,弹出undefined、弹出1。

*注意:函数参数是局部变量,fn1(a) <=> fn1(var a=undefined)

 

 6

1 var a=1;
2 function fn1(a){ // 参数a <=> var a=1
3     alert(a); // 1 这个a不是外面的a;这个是局部的
4     a=2; // 就近原则,改变了局部的a
5 }
6 fn1(a);
7 alert(a); // 1

相当于

1 var a=1;
2 function fn1(b){ //参数b <=> var b=a=1
3     alert(b); //1
4     b=2;
5 }
6 fn1(a);
7 alert(a); // 1

 

当在某个环境中为了读取或写入而引用了一个标识符,必须通过搜索来确定该标识符实际代表什么,搜索过程从作用域链的前端开始,向上级查询与给定名字匹配的标识符。作用域链的前端,始终都是当前执行的代码所在的环境的变量对象,作用域链的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到作用域链的最后一个对象,即全局执行环境。

posted @ 2015-08-28 10:42  aadega  阅读(485)  评论(0)    收藏  举报