使用閉包跨域開發
閉包指詞法表示包括不必計算的變量的函數,閉包函數能夠使用函數外定義的變量。
閉包特性:
(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。
使用閉包跨域開發