初探js閉包

來源:互聯網
上載者:User

標籤:style   blog   io   ar   color   使用   sp   java   for   

1.變數的範圍:全域變數、局部變數

  • 函數內部可以直接讀取局部變數

js代碼

var n=2;

function fun(){

alert(n);

}

fun();  //2

  • 函數外部不能讀取函數內部局部變數

js代碼

function fun(){

var n=2;    //注意這裡要使用var,否則聲明的是全域變數

}

alert(n); //error

  • 下面n聲明為全域變數

js代碼

function fun(){

n=2;}
alert(n); //2

 

2.如何從外部讀取局部變數?

  有時候需要得到函數內部的局部局部變數,正常情況下是辦不到的,只有變通才有可能。在函數內部在定義一個函數

js代碼

function fun(){

var n=2;

function f2(){

alert(n); //2

}

}

上面代碼,f2函數包含在fun函數中,這時fun內部的局部變數對f2是可見的,而f2內部局部變數,對fun不可見,這就是javascript"鏈式範圍"結構

子物件會一級一級向上尋找所有父物件的變數,即父物件的所有變數對子物件都可見,反之則不成立

js代碼

function fun(){

var n=2;

function f2(){

alert(n);

}

return f2;

}

var result=fun();

result(); //2

 

3.閉包概念

上面f2函數就是閉包

閉包簡單理解就是:能夠讀取其他函數內部變數的函數,即將函數內部與函數外部串連起來的橋樑

 

4.閉包的用途

事實上,通過使用閉包,可以做很多事情。比如:類比物件導向的代碼風格;更優雅,更簡潔地表達出代碼;在某些方面提升代碼的執行效率

註:根據上面知識可知,所有的變數如果不加關鍵字,則預設會添加到全域對象的屬性上,臨時變數加入全域變數有很多壞處,如:別的函數可能誤用這些變數,造成全域對象過於龐大,影響訪問速度(因為變數的取值需要從原型鏈上遍曆)

4.1匿名子執行函數

有些函數只需執行一次,其內部變數無序維護,比如UI的初始化,我們可以使用閉包

js代碼

var datamodel={    table:[];    tree:[];}(function(dm){for(var i=0;i<dm.table.rows;i++){        var row=dm.table.rows[i];        for(var j=0;j<row.cells;i++){            drawCell(i,j);        }    }    //build dm.tree})(datamodel);

建立一個匿名函數並立即執行它,由於外部無法引用它內部的變數,因此在執行完後會很快被釋放,最主要的是這種機制不會汙染全域變數

4.2 緩衝

  如果我們正在處理過程很耗時的函數對象,每次調用都會花費很長時間,那麼我們就需要將計算出來的值儲存起來,當調用這個函數的時候,首先在緩衝中尋找,如果找不到,則進行計算,然後更新緩衝並傳回值,如果找到了,直接返回尋找的值即可。

  閉包正是可以做到這一點,因為它不會釋放外部的引用,函數內部的值可以得到保留。減少全域變數,常駐記憶體,可以實現緩衝

js代碼

function f1(){     var n=99;    nAdd=function(){        n+=1;    }    function f2(){        alert(n);    }    return f2; } var result=f1(); result();//99 nAdd(); result();//100

為什麼f1中的局部變數n一直儲存在記憶體中,沒有在f1調用結束後自動清除?

f1是f2的父函數,f2被賦給全域變數,導致f2始終在記憶體中,而f2的存在依賴f1,因此f1也始終在記憶體中,不會再調用結束後,被記憶體回收機制回收

4.3 實現封裝

4.3.1如下例子,在person之外的地方無法訪問其內部的變數,通過提供閉包的形式來訪問

js代碼

 var person=function(){           var name="jack";        return{            getName:function(){                return name;            },            setName:function(newName){                name=newName;            }        }   }();   alert(person.name);       //直接存取結果為:undefined   alert(person.getName());  //jack   person.setName("lihua");    alert(person.getName());  //lihua 

4.3.2

  閉包另一個重要用途是實現物件導向中的對象,傳統的語言都提供類的模板機制,這樣不同的對象(類的執行個體)擁有獨立的成員及狀態,互不干涉。雖然javascript中沒有類這樣的機制,但通過使用閉包,可以類比出這樣的機制。

js代碼

function person(){           var name="jack";        return{            getName:function(){                return name;            },            setName:function(newName){                name=newName;            }        }   };   var jone=person();   alert(jone.getName());  //jack   jone.setName("lihua");    alert(jone.getName());  //lihua       var miss=person();   alert(miss.getName());   miss.setName("wanghai");   alert(miss.getName());

以上代碼中Jone和miss可以成為person這個類的執行個體,因為這兩個執行個體對name這個成員的訪問時獨立的,互補影響。

5使用閉包應該注意問題

5.1記憶體泄露

  閉包會使函數中的變數都儲存在記憶體中,記憶體消耗大,故不能濫用閉包,否則造成網頁效能問題(瀏覽器響應速度慢、降低使用者體驗甚至會造成瀏覽器無響應等現象),在IE中可能導致記憶體泄露

5.2上下文應用

jQuery代碼

$(function(){

var con=$("div#panel");

this.id="content";

con.click(function(){

alert(this.id); //panel

});

});

  this.id 顯示的被賦值content,而在click回調中,形成的閉包引用到this.id,但這個alert會彈出"panel",原因:雖然閉包可以引用局部變數,但此處涉及到this,因為調用對象的存在,使得閉包被調用時(當這個panel的click事件發生時),此處的this引用的是con這個jQuery對象,而匿名函數this.id="content"是對匿名函數本身做的操作。

如果想在事件中處理函數中訪問的這個值,則必須做些改變

$(function(){

var con=$("div#panel");

this.id="content";

var self=this;

con.click(function(){

alert(self.id); //content

});

});

初探js閉包

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.