JS 作用域

作用域

 

执行环境

执行环境,定义了变量或函数有权访问的其它数据,决定了它们各自的行为。

每个执行环境都有一个与之相对应的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

全局环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象,因此,所有全局变量和函数都是作为window对象的属性和方法创建的。

使用var声明的变量会被添加到最接近的环境中;如果初始化变量时没有使用var声明,该变量会被自动添加到全局环境中。

每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境会被推入一个环境栈中;而在环境执行之后,栈将其环境弹出,将控制权返回给之前的执行环境。

 

作用域链

JS中不存在块级作用域,只有函数作用域。

当代码在一个环境中运行时,会创建变量对象的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问;也就是说,每次进入一个新的执行环境,都会创建一个作用域链,用于搜索变量和函数。

作用域链的前端,始终都是当前执行的代码所在环境的变量对象;如果这个变量是函数,则将其活动对象作为变量对象(活动对象在一开始只包含一个变量,即arguments对象);作用域链中的下一个变量对象来自外部环境,而再下一个变量对象则来自再下一个外部环境,这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链的最后一个对象。

标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索过程始终都是从作用域链的前端开始,然后逐级向上,直到找到标识符为止。

局部环境可以通过作用域链访问外部环境中所有的变量和函数;但是外部环境不能访问局部环境中的任何数据;环境之间的联系是线性的,有次序的。

 

延长作用域链

try-catch语句中的catch块;

with语句。

传送门有待补充。。。

 

词法作用域

函数之间的嵌套关系是函数定义时就决定的,而非调用时决定的。

函数的执行环境依赖于变量对象的作用域,这个作用域是在变量定义时决定的,而不是函数调用时决定的。

认识词法作用域:

1 function num() {
2     var a = 10;    //先声明并初始化一个变量a
3     return a;    
4 };
5 var a = 20;    //再声明并初始化一个变量a
6 console.log(num());    //10

 

函数对象可以通过作用域链相互关联起来,函数内部的变量都可以保存在函数作用域内。

函数内无论什么位置声明的变量或函数,在进入函数时,由于声明提升的原因,都是已经声明的,但未初始化。

 

 1 var b = 10;    // b 可以在这里初始化
 2 
 3 (function() {
 4     var a = 10;
 5     // var b = 10;    // b 也可以在这里初始化
 6     add(a,b);
 7 })();
 8 
 9 // var b = 10;    // 但是 b 不可以在这里初始化,结果为 NaN
10 
11 function add(a,b) {
12     console.log(a + b);
13 }

 

 

查询标识符

搜索标识符,首先从作用域链的前端开始,向上逐级查找与给定名字匹配的标识符;只要找到了该标识符,搜索停止,变量就绪。

因此,如果在局部环境中定义了一个和外部环境同名的变量,搜索时首先会搜索到局部环境中的变量,并使用这个变量,外部环境中的变量会被忽略。

示例:

1 var color = "blue";
2 function Color() {
3     var color = "red";
4     return color;
5 };
6 console.log(Color());    //"red"

 

posted @ 2016-07-30 12:41  Aaron_Xiao  阅读(225)  评论(0)    收藏  举报