作用域:
作用域有两种,一种是全局作用域,对应全局变量;另一种是局部作用域,对应的是局部变量。
最外层函数定义的变量拥有全局作用域,对任何内部函数来说,都是可以访问的。
局部作用域一般只在固定的代码片段内可以访问,函数外部是访问不到的。
闭包有权访问另一个函数作用于中的变量,在闭包函数执行时,会将它的外部函数的对象添加到它的作用域中。
ES6之前没有块级作用域,JavaScript的作用域是相对函数而言的。
C++:
for(int i=0;i<5;i++){
//i的作用范围只在这个for循环里面
}
printf("%d",&i); //error
JavaScript:
for(var i=0;i<5;i++){
}
console.log(i); //5
ES6增加了块级作用域,用let声明。
作用域链:
执行环境定义了变量或者函数有权访问的其他数据,决定了它们各自的行为,每个执行环境都有一个与之关联的变量对象。当代码在一个执行环境中执行时,会创建变量对象的作用域链,作用域链是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。
Tips:
- 标识符解析是沿着作用域链一级一级地搜索标识符的过程。
- 内部环境可以通过作用域链访问到所有的外部环境,但是外部环境不能访问内部环境的任何变量和函数。
作用域链的示例如下:(参考JavaScript高级程序设计)
var color = "blue";
function changeColor(){
var anotherColor="red";
function swapColor(){
var tempColor=anotherColor;
anotherColor=color;
color=tempColor;
//这里可以访问color, tempColor, anotherColor.
}
swapColor();
//这里可以访问color和anothColor;但是不能访问tempColor。
}
changeColor();
//这里只能访问color
用图的形式表示以上代码的作用域:
延长作用域链:
有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除,当执行流进入下列任何一个语句时,作用域链就会加长。
- try-catch语句中的catch块;
- with语句。