講解JavaScript中另一個重要的知識——閉包。
5,閉包
閉包意味著內層的函數可以引用存在於包圍它的函數內的變數,即使外層函數的執行已經終止。
讓我們先來看一個閉包的例子。
<script type="text/javascript">
function add(num){
return function(toAdd){
return num+toAdd; //代碼①
}
}
var addFive = add(5); //此時addFive為function(toAdd){return num+toAdd;}
var count = addFive(3); //此時count為 num+toAdd
alert(count);//8
</script>
代碼①是處於函數內層,不過它可以使用外層的變數num。
閉合還能解決另一個常見的Js問題,全域變數的影響。
通過自動執行匿名函數組合閉包,便可把原本屬於全域的變數隱藏起來。看下面的例子:
<script type="text/javascript">
(function(){
var msg = "Hello";
window.onunload = function(){
alert(msg);//輸出Hello
}
})()
//alert(msg);//出現未定義
</script>
在使用setTimeout時,我們經常也用上了閉包。
<html>
<head>
<title>demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
window.onload = function(){
var obj = document.getElementById("abc");
obj.style.border = "1px solid #000";
setTimeout(function(){
obj.style.color = "red";
},1000)
function DeAlert(msg , time){
setTimeout( function(){
alert(msg);
},time)
}
DeAlert("hello",2000);
}
</script>
</head>
<body>
<div id="abc">CssRain</div>
</body>
</html>
以這種方式使用setTimeout(),可以避免一些問題。
當然使用閉包 也會帶來一些問題。如下代碼所示:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
window.onload = function(){
var ul = document.getElementById("abc");
var li = document.getElementsByTagName("li");
for(var i=0;i<li.length;i++){
li[i].onclick = function(){
alert("你單擊的是第"+i+"個li。");
}
}
}
</script>
</head>
<body>
<ul id="abc">
<li>AAA</li>
<li>BBB</li>
<li>CCC</li>
</ul>
</body>
</html>
單擊li彈出的序號為 3 ,並不是正確的序號,它引用的值是最後一次的賦值。
我們可以使用下面代碼來解決:
<script type="text/javascript">
window.onload = function(){
var ul = document.getElementById("abc");
var li = document.getElementsByTagName("li");
for(var i=0;i<li.length;i++){
(function(){ //使用一個自執行的匿名函數 來激發出範圍
var b = i ; //記住在這個範圍內的值
li[b].onclick = function(){ //使用剛才記住的值,變數b
alert("你單擊的是第"+b+"個li。");
}
})()
}
}
</script>
通過使用閉包對範圍的控制,從而符合了我們的要求。
上面的代碼可以分解為:
<script type="text/javascript">
window.onload = function(){
var ul = document.getElementById("abc");
var li = document.getElementsByTagName("li");
function a(){
var b = 0 ;
li[b].onclick = function(){
alert("你單擊的是第"+b+"個li。");
}
}
function b(){
var b = 1 ;
li[b].onclick = function(){
alert("你單擊的是第"+b+"個li。");
}
}
function c(){
var b = 2 ;
li[b].onclick = function(){
alert("你單擊的是第"+b+"個li。");
}
}
a();
b();
c();
}
</script>
閉包的概念不容易掌握,我也是花了大量時間和精力才理解。
6,小結
筆記(2),(3),(4)講解了 JavaScript中的幾個重要的內容,包括引用,函數重載,範圍,內容物件和閉包。
引用的關鍵內容: 指標,數組引用,字串引用,區別,傳值,傳址。
函數重載的關鍵內容: 參數的數量,參數的類型,arguments,偽數組,typeof,constructor,區別-字串和對象。
範圍的關鍵內容: 函數劃分,全域範圍,全域對象,window對象的屬性,局部範圍,顯式聲明,隱式聲明。
內容物件的關鍵內容: this變數,call,apply,參數區別,數組。
閉包的關鍵內容: 內層函數,外層函數,變數,setTimeout,閉包問題,最後一次的賦值,閉包和範圍。