javascript 闭包
所谓“闭包”,就是在构造函数体内定义另外的函数作为目标对象的方法函数,而这个对象的方法函数反过来引用外层外层函数体中的临时变量。 这使得只要目标对象在生存期内始终能保持其方法,就能间接保持原构造函数体当时用到的临时变量值。尽管最开始的构造函数调用已经结束,临时变量的名称也都消失了,但在目标对象的方法内却始终能引用到该变量的值,而且该值只能通这种方法来访问。即使再次调用相同的构造函数,但只会生成新对象和方法,新的临时变量只是对应新的值,和上次那次调用的是各自独立的。
1 function addLink(num)
2 {
3 for(var i=0; i<num; i++)
4 {
5 var link = document.createElement('a');
6 link.innerHTML = "Link " + i;
7 link.onclick = function(){
8 alert(i);
9 };
10 document.body.appendChild(link);
11 }
12 }
13 //可惜的是,当你点击每个链接时,输出的都是 Link 4
14 // 使用closure 可以解决这个问题
15
16 function addLink2(num)
17 {
18 for(var i=0; i<num; i++)
19 {
20 var link = document.createElement('a');
21 link.innerHTML = "Link" + i;
22 link.onclick = function(j){ //使用closure
23 return function(){
24 alert(j);
25 };//返回一个函数
26 }(i);//调用这个函数
27 document.body.appendChild(link);
28 }
29 }
2 {
3 for(var i=0; i<num; i++)
4 {
5 var link = document.createElement('a');
6 link.innerHTML = "Link " + i;
7 link.onclick = function(){
8 alert(i);
9 };
10 document.body.appendChild(link);
11 }
12 }
13 //可惜的是,当你点击每个链接时,输出的都是 Link 4
14 // 使用closure 可以解决这个问题
15
16 function addLink2(num)
17 {
18 for(var i=0; i<num; i++)
19 {
20 var link = document.createElement('a');
21 link.innerHTML = "Link" + i;
22 link.onclick = function(j){ //使用closure
23 return function(){
24 alert(j);
25 };//返回一个函数
26 }(i);//调用这个函数
27 document.body.appendChild(link);
28 }
29 }
上面一段代码中,目标对象是 link元素,外层函数的临时变量是j 目标对象的方法函数是return fucntion(){alert(j);}
这样就使得alert(j)总能引用到i当时的变量值(1、2...num)
总之, 关于closure,你必须记住以下几点:
- 当你在一个函数中使用另一个函数时, 会产生一个closure
- 当你使用eval()时, 会产生一个closure.
- 最好认为closure总是在函数入口处产生,并且本地变量自动添加到closure中
注意事项
- closure就是提供了一种变量共享的机制(内部函数可以访问外部函数的变量)
- 注意closure可能引用的效率问题(如何避免,参见文中详述)
- 具体的应用场景要熟悉
_____________________________________________________________________________________________
closure中小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号对返回的,就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式
(function(){
alert('a');
O=function(id){
return "string"==typeof id?document.getElementById(id):id;
};
})();
alert('a');
O=function(id){
return "string"==typeof id?document.getElementById(id):id;
};
})();
例如:上面一段代码就会自动执行