1. js的作用域作用域链。
执行环境 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。函数执行完之后,栈将其环境弹出,把控制权返回给之前的执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用域链。 (执行环境类型一共两种:全局函数和局部函数)
作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问。
作用域链的前端始终都是当前执行的代码所在环境的变量对象。(如果环境是函数,变量对象则是活动对象。)
活动对象在最开始只包含一个变量,即arguments对象(表示函数的参数,类似于Arrays的对象,通过arguments[0]方式引用,是一个局部变量)。
作用域中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境,一直延续至全局执行环境。全局执行环境的变量对象始终是作用域链的最后一个对象。
在代码运行过程中,标识符解析是沿着作用域一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级向后追溯,直到找到标识符为止。(找不到就报错)
实例代码
var color="blue";
function changeColor() {
if (color=="blue"){
color="red";
}else{
color="blue";
}
}
changeColor();
alert("Color is now"+color);
changeColor()的作用域链包含两个对象:它自己的变量对象(其中定义着arguments对象)和全局变量。可以在函数内部访问变量color,是因为可以在作用域链中找到它。
在局部作用域中定义的变量可以在局部环境中与全局变量互换使用
var color="blue";
function changeColor() {
if (color=="blue"){
color="red";
}else{
color="blue";
}
}
changeColor();
alert("Color is now"+color);
内部环境可以通过作用域链访问到外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些作用域链环境之间的联系是线性的,有次序的。
延长作用域链:有些语句可以在作用域链前端临时增加一个变量对象,该变量对象会在代码执行后被移除。
有两种情况:
-
try-catch语句的catch模块
会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明
注:在IE8之前,catch语句中捕获的错误对象会被添加到执行环境的变量对象,而不是catch语句的变量对象中,即catch块的外部也可以 访问到错误对象 -
with语句
会将指定的对象添加到作用域链中
function a() {
with(location){
....
}
}
location对象中包含了location对象的所有属性和方法,而这个对象被添加到了作用域链的前端