1. 程式人生 > >使用閉包跨域開發

使用閉包跨域開發

依然 func 例如 訪問 執行函數 實施 彈出 示例 完全

閉包指詞法表示包括不必計算的變量的函數,閉包函數能夠使用函數外定義的變量。

閉包特性:

(1)、封閉性:外界無法訪問閉包內的數據,如果在閉包內聲明變量,外界是無法訪問的,除非閉包主動向外界提供訪問接口。

(2)、持久性:對於一般函數來說,在調用完畢後,系統會自動註銷函數,而對於閉包來說,在外部函數被調用之後,閉包結構依然保存在系統中,閉包中的數據依然存在,從而實現數據的持久使用。

function f(x){
var a = x;
var b = function(){
return x;
}
return b;
}
var c = f(1);
alert(c()); //1

在上面示例中,首先在調用函數f結構體內定義兩個變量,分別存儲參數和閉包結構,而閉包結構中寄存著參數值。當調用函數f之後,函數結構被註銷,它的局部變量也隨之被註銷,因此變量a中存儲的參數值也隨之丟失。但由於變量b儲存著閉包結構,因此,閉包函數內部的變量值並沒有被釋放,在調用函數之後,依然能夠用從閉包結構中讀取到參數值。

閉包函數與普通函數主要包括以下類型的表示符:

函數參數(新參變量)、arguments屬性、局部變量、內部函數名、this(指代閉包函數自身)。

this和arguments是系統默認的函數標識符,不需要特別聲明,這些標識符在閉包體內的優先級是(左側優先級大於右側):this —> 局部變量 —> 形參 —>arguments —> 函數名。

例子:

1 function f(x){ //外部函數

2 var a = x; //外部函數的局部變量,並把參數值傳遞給它

3 var b = function(){ //內部函數

4     return a; //訪問外部函數中的局部變量

5};
6    a++; //訪問後,動態更新外部函數的變量

7     return b; //內部函數
8}

9 var c = f(5) //調用外部函數並賦值

10 alert(c()) //調用內部函數,返回外部函數更新後的值 6

第1步:程序變異之後,從第9行開始解析執行,創建上下文環境,創建調用對象,把參數、局部變量、內部的函數轉換為對象屬性。

第2步:執行函數體內代碼。在第6行執行局部變量a的遞加運算,並把這個值傳遞給對象屬性a,內部函數動態保持與局部變量a的聯系,同時更新自己內部調用變量的值。

第3步:外部函數把內部函數返回給全局變量c,實現內部函數的定義,此時c完全繼承了內部函數的所有結構和數據。

第4步:外部函數返回後(即返回值調用完畢)會自動銷毀,內部的結構、標識符和數據也會隨之丟失。

第5步:執行第10行的代碼命令,調用內部函數,此時返回的是外部函數返回時(銷毀之前)保存的變量a所存儲的最新數據值,既返回6.

如果沒有閉包函數的作用,那麽這種數據寄存和傳遞就無法得以實施。

例如:

function f(x){

    var a = x;

    var b = a; //把局部變量的值傳遞給局部變量b

    a++

    return b; //局部變量b

}

var c = f(5);

alert(c) //值為5

通過上面的示例可以很直觀地看到,在沒有閉包函數的輔助下,第8行代碼執行後返回值並沒有與外部函數的局部變量a最後更新的值保持一致。

閉包在程序開發中具有重要的價值,例如,使用閉包結構能夠跟蹤動態環境中數據的實時變化,並即使儲存。

function f(){

    var a = 1;

    var b = function(){

    return a;

}

    a++;

    return b;

}

    var c = f();

    alert(c()); //返回2,而不是1

在上面示例中,閉包中的變量a存儲的值並不是對上面行變量a的值的簡單復制,直到外部函數f調用返回。閉包不會因為外部函數環境的註銷而消失,會始終存在。

<script language = ‘javascript‘ typt=‘text/javascript‘>

function f(){

  var a = 1;

  b = function(){

  alert(a);

}

  c = function(){

  a++;

}

  d = function(x){

  a = x;

}

}

</script>

<button onclick = "f()">按鈕1:(f())()</button><br/>

<button onclick = "b()">按鈕2:(b = function(){alert(a);})()</button><br/>

<button onclick = "b()">按鈕3:(c = function(a++;){alert(a);})()</button><br/>

<button onclick = "b()">按鈕4:(d = function(x){a = x;})(100)</button><br/>

在上面示例中,在函數f中定義了3個閉包函數,它們分別指向寄存局部變量a的值,並根據不同的操作動態跟蹤變量a的值。當在瀏覽器預覽時,首先應該單擊“按鈕1”,調用函數f,生成3個閉包,3個閉包同時指向局部變量a的引用,因此,當函數返回時,這3個函數閉包都沒有被註銷,變量a由於被閉包引而繼續存在。這時,如果繼續單擊按鈕2和按鈕4 ,那麽會有沒有在系統中生成閉包結構,而彈出編譯錯誤。單擊“按鈕3”將動態遞增變量a的值,如果此時單擊“按鈕2”,則會彈出提示值2.如果單擊“按鈕4”,則向變量a傳值100,將動態改變閉包中寄存的值,如果此時點擊“按鈕2”,則會彈出提示值100。

使用閉包跨域開發