虽然执行环境的类型总共只有两种——全局和局部(函数),但还是有办法来延长作用域链的,这么说是因为有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。在两种情况下会发生这种现象。具体来说,就是当执行流进入下列任何语句时,作用域链就会得到加长:
- try-catch语句的catch块。
- with语句。
这两个语句都会在作用域链的前端添加一个变量对象。对with
语句来说,会将指定的对象添加到作用域链中。对catch
语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。下面看一个例子:
var mother = {
name: 'Rose',
age: 30
}
function father(){
var fName = 'Jack';
var name = '张三';
function son(){
var sName = 'son';
with(mother){
var word = 'my name: ' + sName + ', father name: ' + fName +
', mother name: ' + name + ", mother age: " + age;
}
console.log(word);//my name: son, father name: Jack, mother name: Rose, mother age: 30
}
son();
}
father();
首先声明一个对象mother
,包含两个属性:name
和age
,然后定义一个函数father
,里面声明两个变量:fName
和name
,又声明一个函数son
,son
中定义了一个变量sName
和一个with
语句块。我们来看打印的结果,mother name
为对象mother
中的Rose
,而不是函数father
中的张三
,这就是with
语句在起作用。
在Chrome中调试可以发现,如下图:
代码执行到19行with
语句块中时,作用域链的前端增加了一个With Block
作用域,根据作用域链搜索机制,此时的name
应该是Rose
。
再看下图:
代码执行到22行,with
语句块执行结束,with
作用域从作用域链中移除,with
语句块中声明的变量绑定在with
所在的函数中,所以console.log(word)
可以正常输出word
。