JS中的閉包機制

思惟導圖

1、什麼是閉包機制

函數執行造成的私有上下文,即能保護裏面的私有變量不受外界干擾,也能在當前上下文中保存一些信息(前提:造成的上下文不銷燬),上下文中的這種保存和保護機制,就是閉包機制javascript

2、閉包的兩大做用

一、保護做用

在這個上下文中會有一些私有的變量AO(XX),這些私有的變量和外界的變量不會衝突(互不影響)java

二、保存做用

某些狀況下,上下文中的某些內容被外界佔用後,當前上下文並不會出棧銷燬,這樣就會把上下文中的一些信息儲存起來編程

3、閉包的應用

1.利用閉包的保護做用

  • -1).團隊協做開發中;
    • A/B共同開發一個頁面,最後要把代碼合併在一塊兒,爲了防止全局變量的衝突污染,咱們建議每一個開發者,都把本身的代碼放置到一個閉包中(自執行函數執行便可,這樣就是私有的上下文)保護起來
// A的代碼
(function anonymous() {
    /* 自執行函數執行,會造成一個私有的上下文,在這裏聲明+定義的變量或者函數都是私有的 */
    var x = 100,
        y = 200;

    function func() {
        // ...
    }
})();

// B的代碼
~ function anonymous() {
    // console.log(anonymous); //=>函數自己 
    //=>匿名函數設置的函數名只能在函數裏面應用,函數外面是沒法訪問的
    var x = 200,
        n = 0;

    function func() {
        // ...
    }

    function handled() {
        // ...
    }
}();
// console.log(anonymous); //=>Uncaught ReferenceError: anonymous is not defined 
複製代碼
  • -2).封裝一個插件或者類庫等;
    • 爲了防止咱們定義的變量和方法 和 用戶定義的衝突,咱們也是須要把全部寫的代碼放到一個閉包中,例如:jQuery...
/* JQUERY源碼一瞥 */

// typeof window !== "undefined" ? window : this 瀏覽器端window是存在的,因此爲window
(function (global, factory) {
 "use strict";
	// => global===window
	// => factory===function (window, noGlobal){...}
	factory(global);
})(window, function (window, noGlobal) {
	// JQUERY的源碼
}); 
//=> 利用閉包的機制,把JQ源碼看成自執行函數的形參傳給函數,完成執行
複製代碼

2.利用閉包的保存做用

  • -1).在某些需求中,咱們常常須要造成一個閉包,存儲一些值(並且不能銷燬),這樣來供後面的程序運行使用(例如:惰性函數、柯理化函數、compose函數等JS高階編程技巧中,就是基於閉包的保存機制實現的)

此時咱們發現一個問題:每一個人的代碼都獨立了,那咱們每一個人都會用到的公共方法,難道也要都單獨寫一遍?設計模式

有此需求,必然得有解決辦法:瀏覽器

4、閉包內的值暴露給外面使用的兩種方法

需求:咱們須要把某一個閉包(私有上下文)中的值暴露到外面閉包

一、基於window.xxx=xxx暴露到全局

這種辦法雖然能夠實現,可是也會存在衝突,若是咱們每個版塊都須要暴露更多的方法,同時都基於這種方法暴露到全局對象GO上,也可能致使方法之間的衝突函數

(function anonymous() {
    function queryURLParams() {
        // ...
    }

    function sum() {
        // ...
    }

// 想暴露到外面使用,能夠暴露到全局上(賦值給全局對象GO =>window)
    window.queryURLParams = queryURLParams;
    window.sum = sum;
})();
queryURLParams(); //=>window.queryURLParams() 
複製代碼

二、JS中的設計模式:單例設計模式

每個版塊暴露到全局下只有一個變量而已,全部須要供別人調取的方法都在對象中(這樣暴露一個或者多個都無所謂)性能

  • 避免了全局變量的污染,也同時實現了不一樣閉包之間方法的公用性
var utils = (function anonymous() {
    // queryURLParams:獲取URL地址參數信息
    function queryURLParams() {
        // ...
    }

    // sum:實現任意數求和
    function sum() {
        // ...
    }

    // 把須要供外面訪問的變量和方法,賦值給一個對象,最後返回(外層基於VAR utils定義變量來接收便可)
    return {
        queryURLParams: queryURLParams,
        sum: sum
    }; //=>return AAAFFF000;
})();
// console.log(utils); //=>{queryURLParams:函數,sum:函數}
utils.queryURLParams();
utils.sum(); 
複製代碼

utils對象中包含了須要供別人調取使用的方法;此時咱們把utils稱之爲「命名空間」,而對象就是一個空間,空間中包含了當前版塊中的內容,或者是把當前版塊中的內容按照命名空間進行了分組,每個分組都是一個單獨的個體 ui

命名空間

  • 把每個對象值 賦值給變量 =>能夠理解爲,給每個對象的堆內存空間起了個變量名,因此此時能夠把這個變量稱爲 「命名空間」
  • 當前對象中的鍵值對都是 命名空間 中私有的鍵值對

5、閉包的優缺點

一、優勢

  • 上述咱們一直說的保護和保存做用

二、缺點

  • 由於閉包會產生不銷燬的上下文,這樣致使棧/堆內存消耗過大,有時候也會致使內存泄漏等,影響頁面的運行性能,因此在真實項目中,要合理應用閉包(不要濫用)
相關文章
相關標籤/搜索