1. 程式人生 > >閉包與垃圾回收機制

閉包與垃圾回收機制

直接 不能 失去 fun 才會 define 局部變量 () 避免

一、閉包
1.變量作用域:函數內部可以訪問函數外部的全局變量,但是函數外部卻無法訪問到函數內部的變量。函數內部要使用var聲明變量,如果不用,實際上聲明的是一個全局變量。
2. 如何從外部讀取函數內部的局部變量:有時候我們為了訪問到函數內部的局部變量,我們可以在函數內部,再定義一個函數。
``
function f1(){
var n1=999;
function f2(){
alert(n1);
}
}
``
以上代碼中,函數f1中的所有變量對函數f2都是可見的,但是反過來不行,f2內部的變量對f1都是不可見的。
這就是javascript中的鏈式作用域結構。子對象會一級一級向上尋找父對象,所以父對象裏的變量對子對象都是可見的,但是子對象的變量,父對象無法訪問。
代碼如下:
``
function f1(){
var n1=999;
function f2(){
alert(n1);
}2017-08-282017-08-28
return f2;
}
var n=f1();
n();
//等同於:f1()();
``
以上代碼中f2函數,就是閉包。
3.閉包的概念:能夠訪問到其他函數內部變量的函數就是閉包。閉包本質上就是將函數內部和函數外部連接起來的橋梁。
4.閉包的用途:
a.一個是可以讀取函數內部的變量,封裝的時候就要用到閉包的這一效果。
``
var person = function(){
//變量作用域為函數內部,外部無法訪問
var name = "default";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();

print(person.name);//直接訪問,結果為undefined
print(person.getName());
person.setName("abruzzi");
print(person.getName());

得到結果如下:

undefined
default
abruzzi

``


b.另一個是讓變量的值始終保存在內存中,不會在f1函數調用後,被自動清除,這就是緩存功能,如果結果在緩存中,那麽直接返回緩存中的對象,如果緩存中沒有,再重新執行函數。
因為f1是f2的父函數,f2又被賦給了一個全局變量,這導致f2始終在內存中,又因為f2依賴f1,所以f1也會保持在內存中,不會在函數被調用後被垃圾回收機制清除。

c.避免全局變量汙染函數,函數內部用var聲明變量,這樣外部不會引用到。
##全局變量汙染:代碼中全局變量過多,導致頁面中的代碼都共享了這些全局變量,這就會導致變量的使用出現混亂。
5.註意點:閉包會使得函數中的變量被保存在內存中,所以不能濫用閉包,否則會影響瀏覽器的性能,在ie中會導致內存泄露,解決方法是,在退出函數前,將不使用的局部變量全部刪除。

6.刪除函數中的局部變量:
``
var f1=(function () {
var n1 = 999;
return {
add: function f2() {
console.log(n1);
},
clear: function f3() {
n1 = null;
}
}
})();
``
外部無法訪問到閉包內的變量,但是可以在函數內部返回一個方法,將閉包內部的變量設置為null,讓變量失去引用,會被系統自動回收。


二、垃圾回收機制
原理:全局變量的聲明周期一直會持續到瀏覽器頁面關閉才會清除,而局部變量只在函數執行器中存在,在這個過程中函數會為局部變量分配相應的內存,來存儲它們的值,當函數要使用時才會把變量的值取出來使用,一旦函數結束,局部變量就不再需要了,這時候就會釋放它們的內存,清除局部變量。

閉包與垃圾回收機制