前端面试题-js闭包-7种解决办法

JavaScript 前端客 5348℃ 0评论

问题:
什么是闭包?以下代码点击会输出什么?为什么?能大概说明白的话继续问能想出几种解决办法。

<!DOCTYPE HTML> 
<html> 
<head> 
<meta charset="utf-8" /> 
<title>闭包演示</title> 
<style type="text/css"> 
 p {background:gold;} 
</style> 
<script type="text/javascript"> 
function init() { 
 var pAry = document.getElementsByTagName("p"); 
 for( var i=0; i<pAry.length; i++ ) { 
 pAry[i].onclick = function() { 
 alert(i); 
 } 
 } 
} 
</script> 
</head> 
<body onload="init();"> 
<p>产品 0</p> 
<p>产品 1</p> 
<p>产品 2</p> 
<p>产品 3</p> 
<p>产品 4</p> 
</body> 
</html> 
答案:弹出的结果都是5.
出错:获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。
出错原因:初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。

解决方法:见html代码注释部分

1
<!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].onclick=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].onclick=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].onclick=function(){
 alert(temp);
 }
 })();
 };
}



//加一层闭包,返回一个函数作为响应事件
function init(){
 var pAry=document.getElementsByTagName("p");
 for (var i = 0; i < pAry.length; i++) {
 pAry[i].onclick=function(arg){
 return function(){
 alert(arg);
 }
 }(i);
 };
}



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

 };
}

function init(){
 var pAry=document.getElementsByTagName("p");
 for (var i = 0; i < pAry.length; i++) {
 pAry[i].onclick=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 onload="init();"> 
<p>产品 0</p> 
<p>产品 1</p> 
<p>产品 2</p> 
<p>产品 3</p> 
<p>产品 4</p> 
</body> 
</html>
版权所有,转载请注明:前端客 » 前端面试题-js闭包-7种解决办法
喜欢 (2)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)