function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
}
return innerFun; //注意这里
}
/*
1.执行前:outerFun[[scope]]->window
2.outerFun执行创建执行上下文,建立活动对象{}
3.将形参初始化为arguments对象加入到活动对象。{arguments:{}}
4.将活动对象加入到outerFun的作用域链的前端。scope chain:{arguments:{}}->[[scope]]
5.执行变量实例化。活动对象加入函数实参,内部函数和内部变量。scope chain:{arguments:{}, a:undefined, innerFun:function(){...}}->[[scope]]
6.第5步中定义函数对象innerFun。innerFun[[scope]]指向outerFun函数的scope chain。
7.this赋值,赋值为null即指向window
8.innerFun被obj1引用。
形成如下引用关系:
obj->innerFun
innerFun[[scope]]->outerFun/scope chain/
outerFun/scope chain/ = {arguments:{}, a:undefined, innerFun:function(){...}}->outerFun[[scope]]
*/
var obj1=outerFun();
/*
调用obj1访问a变量,实际是访问到为outerFun创建执行上下文时生成的活动对象的属性a。
*/
obj1(); //结果为1
/*
与上面访问一致
*/
obj1(); //结果为2
/*
将重新为outerFun创建执行上下文
*/
var obj2=outerFun();
/*
调用obj2访问a变量,实际上访问到的是重新为outerFun创建执行上下文时生成的活动对象的属性a。
*/
obj2(); //结果为1
/*
与上面访问一致
*/
obj2(); //结果为2
/*
两次调用outerFun都创建了活动对象,互不影响
*/
obj1(); //结果为3