文章目录
  1. 1. 闭包的三种实现
  2. 2. 闭包使用案例

闭包的三种实现

  • with语句

    1
    2
    3
    with(obj){
    //这里是对象闭包
    }
  • 函数体

    1
    2
    3
    (function(){
    //函数闭包
    })()
  • catch语句

    1
    2
    3
    4
    5
    try{
    //...
    } catch(e) {
    //catch闭包 但IE里不行
    }

一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function User( properties ) {    
//这里一定要声明一个变量来指向当前的instance
var objthis = this;
for ( var i in properties ) {
(function(){
//在闭包内,t每次都是新的,而 properties[i] 的值是for里面的
var t = properties[i];
objthis[ "get" + i ] = function() {return t;};
objthis[ "set" + i ] = function(val) {t = val;};
})();
}
}

//测试代码
var user = new User({
name: "Bob",
age: 44
});

alert( user.getname());//BOb
alert( user.getage());//44

user.setname("Mike");
alert( user.getname()); //Mike
alert( user.getage()); //44

user.setage( 22 );
alert( user.getname()); //Mike
alert( user.getage()); //22

闭包使用案例

让下面这三个节点的Onclick事件都能正确的弹出相应的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>
<li id="a1">aa</li>
<li id="a2">aa</li>
<li id="a3">aa</li>
</ul>

<script type="text/javascript">

for(var i=1; i < 4; i++){
var id = document.getElementById("a" + i);
id.onclick = function(){
alert(i);//现在都是返回4
}
}
</script>

在上面这段代码中,通过for循环为三个li元素注册了click事件。在循环结束后i的值4,这个值是个全局变量。当触发click事件时,处理函数返回的是全局对象i,这个值与事件注册时的i值比已经发生了改变,所以实际返回值都是4.

解决方法:

  1. 使用闭包函数
    1
    2
    3
    4
    5
    6
    7
    8
    var lists = document.getElementsByTagName("li");
    for(var i=0,l=lists.length; i < l; i++){
    lists[i].onclick = (function(i){//保存于外部函函数
    return function(){
    alert(i);
    }
    })(i);
    }


1
2
3
4
5
6
7
8
9
var lists = document.getElementsByTagName("li");
for(var i=0,l=lists.length; i < l; i++){
lists[i].onclick = new function(){
var t = i;
return function(){
alert(t+1)
}
}
}

  1. 利用事件代理

    1
    2
    3
    4
    5
    6
    7
    8
    var ul = document.getElementsByTagName("ul")[0];
    ul.onclick = function(){
    var e = arguments[0] || window.event,
    target = e.srcElement ? e.srcElement : e.target;
    if(target.nodeName.toLowerCase() == "li"){
    alert(target.id.slice(-1))
    }
    }
  2. 将暂时变量保留于元素节点上

    1
    2
    3
    4
    5
    6
    7
    var lists = document.getElementsByTagName("li");
    for(var i=0,t=0,el; el = list[i++];){
    el.i = t++
    el.onclick = function(){
    alert(this.i)
    }
    }
  3. 使用with语句造成的对象闭包

    1
    2
    3
    4
    5
    var els = document.getElementsByTagName("li")
    for(var i=0,n=els.length;i<n;i++){
    with ({i:i})
    els[i].onclick = function() { alert(this.innerHTML+i) };
    }
  4. 使用try…catch语句构造的异常闭包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var lists = document.getElementsByTagName("li");
    for(var i=0,l=lists.length; i < l; i++){
    try{
    throw i;
    }catch(i){
    lists[i].onclick = function(){
    alert(i)
    }
    }
    }
文章目录
  1. 1. 闭包的三种实现
  2. 2. 闭包使用案例