JacaScript 閉包(一)什么是閉包

之前傻傻分不清 匿名函數閉包 這兩個概念,因此經常混用。閉包 是指有權訪問另一個函數作用域中的變量的函數。創建閉包的常見方式,就是在一個函數內部創建另一個函數。

function createComparisonFunction(propertyName) {
    return function(object1, object2) {
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];

        if (value1 < value2) {
            return -1;
        } else if (value1 > value2) {
            return 1;
        } else {
            return 0;
        }
    }
}

上例 return 了一個匿名函數,該函數內部使用了 propertyName 變量,而這個變量是外部函數中的成員,即使這個匿名函數被返回了,且在其他地方被調用了,它仍然可以訪問變量 propertyName

之所以還能訪問這個變量,是因為內部函數的作用域鏈中包含 createComparisonFunction() 的作用域。要徹底搞清楚其中的細節,必須從理解函數第一次被調用的時候都會發生什么入手。

當某個函數第一次被調用時,會創建一個執行環境及相應的作用域鏈,并把作用域鏈賦值給一個特殊的內部屬性(Scope)。然后,使用this、arguments和其他命名參數的值來初始化函數的活動對象(activation object)。但在作用域鏈中,外部函數的活動對象始終處于第二位,外部函數的外部函數的活動對象處于第三位,......直至作為作用域重點的全局執行環境。

在函數執行過程中,為讀取和寫入變量的值,就需要在作用域鏈中查找變量。

function compare(value1, value2) {
    if (value < value2) {
        return -1
    } else if (value1 > value2) {
        return 1;
    } else {
        return 0;
    }
}

var result = compare(5, 10);

上例代碼先定義了 compare() 函數,然后又在全局作用域中調用了它。當第一次調用 compare() 時,會創建一個包含 this 、 arguments 、 value1 和 value2 的活動對象。全局執行環境的變量對象(包含 this 、 result和 compare )在 compare() 執行環境的作用域鏈中則處于第二位。

Paste_Image.png

看到這張圖我首先是悶逼的,包括閉包這一章,我已經反復度了多變,有一天靈關一閃,想說如果是我來實現這個閉包我會怎么玩??

先調用函數自身的作用域鏈,然后想尋找外圍的作用域,一直到頂。

要實現這個效果挺簡單的呀,弄一個數組,按順序把他們的變量存起來,在調用的時候遍歷一遍數組中的成員,看看有沒有我需要的變量不就成了嗎?

抱著這個想法再來看這張圖,中間的那個數組不就是我想要的東西嗎?因為這個函數只有一成,所以最外層的就是全局作用域了,數組0是函數本身,數組1是全局作用域。

函數指針指向的是這個數組,而這個指針同時又由全局作用域中的一個變量存儲,臥槽,全通了,那么如果在函數內部在加上一個變量,是不是數組的成員就多了一位,在數組的起始位置保存該函數的作用域,這個數組就達到了我想要的效果。

于是抱著想法繼續往下看...

var compare = createComparisonFunction("name");
var result = compare({ name: "Bert"}, {name: "Greg"});

從 createComparisonFunction() 中被返回后,它的作用域鏈被初始化為包含 createComparisonFunction() 函數的活動對象和全局變量對象。這樣,匿名函數就可以訪問在 createComparisonFunction() 中定義的所有變量。更為重要的是 createComparisonFunction() 函數在執行完畢后,其活動對象也不會被銷毀,因為匿名函數的作用域鏈仍然在引用這個活動對象。

當 createComparisonFunction() 函數返回后,其執行環境的作用域鏈會被銷毀,但它的活動對象仍然會留在內存中;知道匿名函數被銷毀后, createComparisonFunction() 的活動對象才會被銷毀。

var compareNames = createComparospmFimctopm("name");

// 調用函數
var result = compare({ name: "Bert"}, {name: "Greg"});

// 接觸對你們函數的引用(以便釋放內存)

compareNames = null;
Paste_Image.png

看到這張圖,臥槽,就是這個樣,一個數組0是自建,1是父級,2是全局,如果父級多了就以此類推。

由于閉包會攜帶包含它的函數的作用域,因此會比其他函數占用更多的內存。過度使用閉包可能會導致內存占用過多,建議只在絕對必要時再考慮使用閉包。雖然像V8等優化后的JavaScript引擎會嘗試回收被閉包占用的內存,但還是要慎重使用閉包

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容

  • ● 閉包基礎 ● 閉包作用 ● 閉包經典例子 ● 閉包應用 ● 閉包缺點 ● 參考資料 1、閉包基礎 作用域和作...
    lzyuan閱讀 959評論 0 0
  • 作用域和閉包是 JavaScript 最重要的概念之一,想要進一步學習 JavaScript,就必須理解 Java...
    劼哥stone閱讀 1,192評論 1 13
  • 2016年10月24日 星期天 長沙 多云有雨 經過一周滿滿的工作,難得不加班的周末讓女人的心情不錯。剛巧碰上下雨...
    咸魚臭嗎閱讀 237評論 0 0
  • 同事自己采了一些水芹菜,大家分的,本來我沒搶到的,但另一個同事讓給我了…… 為了水芹菜味兒濃些,我只放了一點點肉……
    風箏2017閱讀 387評論 0 0
  • 夏天的風還未吹來,窗外知了的聲聲聒噪已讓人感受到暑日里的味道。六月初夏的時節,梔子花開,校園漫天別離,即將離校的畢...
    安若玲閱讀 422評論 0 0