前端開發(fā):javascript閉包入門理解
案例
首先看下閉包的一個(gè)簡單案例
- function A(){
- function B(){
- console.log("Hello haorooms!");
- }
- return B;}var c = A();c();//Hello haorooms!
這個(gè)例子是一個(gè)比較簡單的閉包,解釋如下:
(1)定義了一個(gè)普通函數(shù)A
(2)在A中定義了普通函數(shù)B
(3)在A中返回B(確切的講,在A中返回B的引用)
(4)執(zhí)行A(),把A的返回結(jié)果賦值給變量 c
(5)執(zhí)行 c()
當(dāng)一個(gè)內(nèi)部函數(shù)被其外部函數(shù)之外的變量引用時(shí),就形成了一個(gè)閉包。
閉包的作用
在上述例子中,B定義在A中,因此B依賴于A,而外部變量 c 又引用了B, 所以A間接的被 c 引用,也就是說,A不會(huì)被回收,會(huì)一直保存在內(nèi)存中。為了證明我們的推理,上面的例子稍作改進(jìn)。
- function A(){
- var count = 0;
- function B(){
- count ++;
- console.log(count);
- }
- return B;}var c = A();c();// 1c();// 2c();// 3
count是A中的一個(gè)變量,它的值在B中被改變,函數(shù)B每執(zhí)行一次,count的值就在原來的基礎(chǔ)上累加1。因此,A中的count一直保存在內(nèi)存中。
這就是閉包的作用,有時(shí)候我們需要一個(gè)模塊中定義這樣一個(gè)變量:希望這個(gè)變量一直保存在內(nèi)存中但又不會(huì)“污染”全局的變量,這個(gè)時(shí)候,我們就可以用閉包來定義這個(gè)模塊。
常見的閉包寫法
前面我的文章中多次提及“自調(diào)用匿名函數(shù)”,大部分自調(diào)用匿名函數(shù)都是閉包的一種應(yīng)用和寫法。
例如下面的例子
- (function(document){
- var viewport;
- var obj = {
- init:function(id){
- viewport = document.querySelector("#"+id);
- },
- addChild:function(child){
- viewport.appendChild(child);
- },
- removeChild:function(child){
- viewport.removeChild(child);
- }
- }
- window.jView = obj;})(document);
以上代碼可以改寫成如下代碼:
- var f = function(document){
- var viewport;
- var obj = {
- init:function(id){
- viewport = document.querySelector("#"+id);
- },
- addChild:function(child){
- viewport.appendChild(child);
- },
- removeChild:function(child){
- viewport.removeChild(child);
- }
- }
- window.jView = obj;};f(document);
在這段代碼中似乎看到了閉包的影子,但 f 中沒有任何返回值,似乎不具備閉包的條件,注意這句代碼:
- window.jView = obj;
obj 是在 f 中定義的一個(gè)對象,這個(gè)對象中定義了一系列方法, 執(zhí)行window.jView = obj 就是在 window 全局對象定義了一個(gè)變量 jView,并將這個(gè)變量指向 obj 對象,即全局變量 jView 引用了 obj 。而 obj 對象中的函數(shù)又引用了 f 中的變量 viewport ,因此 f 中的 viewport 不會(huì)被回收,會(huì)一直保存到內(nèi)存中,所以這種寫法滿足閉包的條件。 另外,我們把obj賦值給window.jView ,那么,我們在整個(gè)window中可以直接調(diào)用obj 中的函數(shù),但是函數(shù)內(nèi)部的變量不會(huì)被收回,例如我們調(diào)用obj的init函數(shù)可以這么寫:
- window.jView.init("haorooms")
小結(jié)
以上是對閉包最簡單的理解。當(dāng)然閉包還有更深入的理解。例如執(zhí)行環(huán)境(execution context)、活動(dòng)對象(activation object)以及作用域(scope)和作用域鏈(scope chain)的運(yùn)行機(jī)制等等。當(dāng)然,我們理解閉包先從簡單開始,寫的多了,理解的就越深了。本文也是對閉包的最簡單的入門,希望通過這篇文章,大家對閉包有了一定的理解。
【本文為51CTO專欄作者“謝軍”的原創(chuàng)稿件,轉(zhuǎn)載可通過作者微信公眾號(hào)(jingfeng18)獲取聯(lián)系】