JavaScript闭包示例

在下面的例子中,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4。

 <html>
<head>
<meta charset="utf-8" />
<title>闭包演示</title>
<style type="text/css">
p {background:#ccc;}
</style>
<script type="text/javascript">
window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = function() {
alert(i);
}
}
}
</script>
</head>
<body>
<p>000</p>
<p>111</p>
<p>222</p>
<p>333</p>
<p>444</p>
</body>
</html>

原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加 点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。

方法1:将变量 i 保存给在每个段落对象(p)上

  window.onload = function(){
var arr = document.getElementsByTagName('p');
for(var i=0; i<arr.length; i++){
arr[i].i= i; //或 arr[i].index = i;
arr[i].onclick = function(){
alert(this.i); //或alert(this.index);
}
}
}

方法2:加一层闭包,i 以函数参数形式传递给内层函数

window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(arg){
arr[i].onclick = function() {
alert(arg);
};
})(i);//调用时参数
}
}

方法3:将变量 i 保存在匿名函数自身

 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
(arr[i].onclick = function() {
alert(arguments.callee.i);
}).i = i;
}
}

4、加一层闭包,i 以局部变量形式传递给内层函数

 1 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
(function () {
var temp = i;//调用时局部变量
arr[i].onclick = function() {
alert(temp);
}
})();
}
}

5、加一层闭包,返回一个函数作为响应事件(注意与2的细微区别)

 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = function(arg) {
return function() {//返回一个函数
alert(arg);
}
}(i);
}
}

6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

  window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = new Function("alert(" + i + ");"); //new一次就产生一个函数实例
}
}

7、用Function实现,注意与6的区别

 window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = Function('alert('+i+')');
}
}
上一篇:android解析网络json数据(1)


下一篇:java面试题(杨晓峰)---第七讲谈谈int和integer有什么区别?