例1:
var obj = new Object();
var events = {m1: 'clicked', m2: 'changed'};
for (var e in events) {
(function() {
var aValue = e;
obj[e] = function() {
//var aValue = e;
console.log(events[aValue]);
};
}());
};
console.log(obj.m1 === obj.m2); //false
obj.m1(); //clicked
obj.m2(); //changed
例2:
var obj = new Object();
var events = {m1: 'clicked', m2: 'changed'};
for (var e in events) {
(function() {
//var aValue = e;
obj[e] = function() {
var aValue = e;
console.log(events[aValue]);
};
}());
};
console.log(obj.m1 === obj.m2); //false
obj.m1(); //changed
obj.m2(); //changed
以上两个例子中,除了var aValue = e;这一句位置不同:例1位于外层匿名函数中、例2位于内层匿名函数中,其他部分完全相同。但结果令我困惑,为什么?哪位帮忙分析下?谢谢!
—————————————————————————————————————————
PS.目前我的理解,一般来讲,同一个外层函数中的不同闭包(内层函数)的作用域链(本质上是一个指向变量对象的指针列表,参见《JavaScript高级程序设计(第3版)》P.179正文倒数第2段及P.180图7-2)引用的是外层函数的同一个活动对象;但是在例1中,因为立即执行函数两次独立执行的缘故,导致创建了两个不同的外层函数的活动对象,从而每个闭包的作用域链各自引用了其中的一个活动对象。如果有误,还望指教。
闭包在函数声明的时候生成,它确定的是变量的查找路径而不是变量的值;变量的值在函数执行时才能确定
D行定义了一个立即执行函数,函数在执行时引用了当前循环的
e
值并赋值给立即执行函数的局部变量aValue
,B行定义了匿名函数,并且为obj对象添加了e
表示的字符串值为属性名的一个属性,并且绑定到匿名函数。匿名函数使用到了D行定义的立即执行函数的局部变量aValue
,立即执行函数完毕后,B行匿名函数有对立即执行函数的闭包,确定匿名函数中需要的变量aValue
到立即函数中查找下一次循环时,
e
变量指向的值发生变化,但先前生成的B匿名函数引用aValue
变量值是不会跟着变化的,aValue
变量值是确定的,在立即执行函数中。每次循环B行声明的匿名函数对象都是不同的,立即执行函数对象也是不同的
因为有变量应用关系的存在,匿名立即执行函数不会被释放掉,其局部变量也会得到保留~~~
和上面不同的地方将A行移动到A1行,看着似乎差不多,但是结果却不同
原因就在于B处声明的匿名函数,引用了最外层的变量e,构成对对外层函数的闭包;只是确立了变量引用了关系(确切的说确定了变量查找路径),但是具体的值在函数被执行前是无法预知的
等整个循环结束后,
e
的值为m2(这个也不一定,看events属性定义的顺序及属性值的获取手段),当obj属性绑定的函数被执行时,A1行aValue
都为m2~~~~