閉包的定義非常晦澀——閉包,是指語法域位於某個特定的區域,具有持續參照(讀寫)位於該區域內自身范圍之外的執行域上的非持久型變量值能力的段落。這些外部執行域的非持久型變量神奇地保留它們在閉包最初定義(或創建)時的值(深連結)。簡單來說,閉包就是在另一個作用域中保存了一份它從上一級函數或作用域取得的變量(鍵值對),而這些鍵值對是不會隨上一級函數的執行完成而銷毀。周愛民說得更清楚,閉包就是“屬性表”,閉包就是一個數據塊,閉包就是一個存放著“Name=Value”的對照表。就這麼簡單。但是,必須強調,閉包是一個運行期概念。
在Javascript中閉包(Closure),有兩個特點:
作為一個函數變量的一個引用 - 當函數返回時,其處於激活狀態。
一個閉包就是當一個函數返回時,一個沒有釋放資源的棧區。
現在比較讓人認同的閉包實現有如下三種
with(obj){
//這裡是對象閉包
}
(function(){
//函數閉包
})()
try{
//...
} catch(e) {
//catch閉包 但IE裡不行
}
幾個有用的示例
//*************閉包uniqueID*************
uniqueID = (function(){ //這個函數的調用對象保存值
var id = 0; //這是私有恆久的那個值
//外層函數返回一個有權訪問恆久值的嵌套的函數
//那就是我們保存在變量uniqueID裡的嵌套函數.
return function(){return id++;}; //返回,自加.
})(); //在定義後調用外層函數.
document.writeln(uniqueID()); //0
document.writeln(uniqueID()); //1
document.writeln(uniqueID()); //2
document.writeln(uniqueID()); //3
document.writeln(uniqueID()); //4
//*************閉包階乘*************
var a = (function(n){
if(n<1){ alert("invalid arguments"); return 0; }
if(n==1){ return 1; }
else{ return n * arguments.callee(n-1); }
})(4);
document.writeln(a);
function User( properties ) {
//這裡一定要聲明一個變量來指向當前的instance
var objthis = this;
for ( var i in properties ) {
(function(){
//在閉包內,t每次都是新的,而 properties[i] 的值是for裡面的
var t = properties[i];
objthis[ "get" + i ] = function() {return t;};
objthis[ "set" + i ] = function(val) {t = val;};
})();
}
}
//測試代碼
var user = new User({
name: "Keleyi",
age: 44
});
alert( user.getname());
alert( user.getage());
user.setname("Mike");
alert( user.getname());
alert( user.getage());
user.setage( 22 );
alert( user.getname());
alert( user.getage());