什么是闭包?以下代码点击<p> 会输出什么?为什么?能大概说明白的话继续问能想出几种解决办法。
==========
出错:获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。
出错原因:初学者并未理解JavaScript的闭包特性。通过element.οnclick=function(){alert(i);}方式给元素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。
解决方法:见html代码注释部分
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>闭包演示</title>
<style type="text/css">
p {background:gold;}
</style>
<script type="text/javascript">
/* 网上的七种方法
//将变量 i 保存给在每个段落对象上
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].i=i;
pAry[i].onclick = function() {
alert(this.i);
}
}
}
//将变量i保存在匿名函数自身
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i <pAry.length; i++) {
(pAry[i].οnclick=function(){
alert(arguments.callee.i)
}).i=i;
};
}
//加一层闭包,i以函数参数形式传递给内层函数
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
(function(arg){
pAry[i].οnclick=function(){
alert(arg);
};
})(i);//调用时参数
};
}
//加一层闭包,i 以局部变量形式传递给内层函数
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
(function(){
var temp=i;//调用时局部变量
pAry[i].οnclick=function(){
alert(temp);
}
})();
};
}
//加一层闭包,返回一个函数作为响应事件
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].οnclick=function(arg){
return function(){
alert(arg);
}
}(i);
};
}
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].οnclick=new Function("alert("+i+");");//new一次就产生一个函数实例
};
}
function init(){
var pAry=document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].οnclick=Function("alert("+i+");");
};
}
*/
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function() {
alert(i);
}
}
}
</script>
</head>
<body οnlοad="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>