1. 程式人生 > >前端面試題——js閉包

前端面試題——js閉包

什麼是閉包?以下程式碼點選<p> 會輸出什麼?為什麼?能大概說明白的話繼續問能想出幾種解決辦法。

==========

出錯:獲取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程式碼註釋部分


<!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>