在Javascript中,什麼是閉包(Closure)

來源:互聯網
上載者:User
閉包的兩個特點:

1、作為一個函數變數的一個引用 - 當函數返回時,其處於啟用狀態。
2、一個閉包就是當一個函數返回時,一個沒有釋放資源的棧區。

例1。<script type="text/javascript">
function sayHello2(name) {
 var text = 'Hello ' + name; // local variable
 var sayAlert = function() { alert(text); }
 return sayAlert;
}
var sy = sayHello2('never-online');
sy();
</script>

作為一個Javascript程式員,應該明白上面的代碼就是一個函數的引用。如果你還不明白或者不清楚的話,請先瞭解一些基本的知識,我這裡不再敘述。

上面的代碼為什麼是一個閉包?
因為sayHello2函數裡有一個內嵌匿名函數
sayAlert = function(){ alert(text); }
在Javascript裡。如果你建立了一個內嵌函數(如上例),也就是建立了一個閉包。

在C
或者其它的主流語言中,當一個函數返回後,所有的局部變數將不可訪問,因為它們所在的棧已經被消毀。但在Javascript裡,如果你聲明了一個內嵌函
數,局部變數將在函數返回後依然可訪問。比如上例中的變數sy,就是引用內嵌函數中的匿名函數function(){ alert(text);
},可以把上例改成這樣:<script type="text/javascript">
function sayHello2(name) {
 var text = 'Hello ' + name; // local variable
 var sayAlert = function() { alert(text); }
 return sayAlert;
}
var sy = sayHello2('never-online');
alert(sy.toString());
</script>

這裡也就與閉包的第二個特點相吻合。

例2。<script type="text/javascript">
function say667() {
 // Local variable that ends up within closure
 var num = 666;
 var sayAlert = function() { alert(num); }
 num++;
 return sayAlert;
}

var sy = say667();
sy();
alert(sy.toString());
</script>

上面的代碼中,匿名變數function() { alert(num); }中的num,並不是被拷貝,而是繼續引用外函數定義的局部變數——num中的值,直到外函數say667()返回。

例3。<script type="text/javascript">
function setupSomeGlobals() {
 // Local variable that ends up within closure
 var num = 666;
 // Store some references to functions as global variables
 gAlertNumber = function() { alert(num); }
 gIncreaseNumber = function() { num++; }
 gSetNumber = function(x) { num = x; }
}

</script>
<button onclick="setupSomeGlobals()">產生 - setupSomeGlobals()</button>
<button onclick="gAlertNumber()">輸出值 - gAlertNumber()</button>
<button onclick="gIncreaseNumber()">增加 - gIncreaseNumber()</button>
<button onclick="gSetNumber(5)">賦值5 - gSetNumber(5)</button>

上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一個閉包的引用,setupSomeGlobals(),因為他們聲明都是通過同一個全域調用——setupSomeGlobals()。
你可以通過“產生”,“增加”,“賦值”,“輸出值”這三個按扭來查看輸出結果。如果你點擊“產生”按鈕,將建立一個新閉包。也就會重寫gAlertNumber(), gIncreaseNumber(), gSetNumber(5)這三個函數。

如果理解以上代碼後,看下面的例子:

例4。<script type="text/javascript">
function buildList(list) {
 var result = [];
 for (var i = 0; i < list.length; i++) {
 var item = 'item' + list[i];
 result.push( function() {alert(item + ' ' + list[i])} );
 }
 return result;
}

function testList() {
 var fnlist = buildList([1,2,3]);
 // using j only to help prevent confusion - could use i
 for (var j = 0; j < fnlist.length; j++) {
 fnlist[j]();
 }
}

testList();
</script>
運行結果:
item 3 is undefined
item 3 is undefined
item 3 is undefined

代碼result.push( function() {alert(item + ' ' + list[i])} ),
使result數組添加了三個匿名函數的引用。這句代碼也可以寫成
var p = function() {alert(item + ' ' + list[i])};
result.push(p);

關於為什麼會輸出三次都是 "item 3 is undefined"

在上面的例子say667()例子中已經解釋過了。

名函數function() {alert(item + ' ' +
list[i])}中的list[i]並不是經過拷貝,而是對參數list的一個引用。直到函數buildList()返回為止,也就是說,返回最後一個
引用。即遍曆完list(註:list的最大下標應該是2)後,經過i++也就變成了3,這也就是為什麼是item
3,而list[3]本身是沒有初始化的,自然也就是undefined了。

例5。<script type="text/javascript">
function newClosure(someNum, someRef) {
 // Local variables that end up within closure
 var num = someNum;
 var anArray = [1,2,3];
 var ref = someRef;
 return function(x) {
 num += x;
 anArray.push(num);
 alert('num: ' + num + 
 'nanArray ' + anArray.toString() + 
 'nref.someVar ' + ref.someVar);
 }
}
var closure1 = newClosure(40, {someVar:' never-online'})
var closure2 = newClosure(99, {someVar:' BlueDestiny'})
closure1(4)
closure2(3)
</script>

在這最後一個例子中,展示如何聲明兩個不同的閉包。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.