javascript 高級 ---- 閉包

var getAuthor = (function (){? ? ? ? 今天我們來談談閉包的概念和理解。閉包設計的理念也是為提高計算機的運行效率。因為上一章我們講過變量的提升機制,來提高計算機查詢變量的的效率。但是在程序設計的時候,我們對變量的內存是大多,提高利用效率。有時候我們需要保持一些局部變量長期保持,可以在全局作用域利用。第二呢,由于js沒有塊級概念,這樣造成變量的利用效率低下。程序復雜時,需要大量的變量,在我們在命名變量時,就造成麻煩。所以,我們設計了閉包的概念和程序語言。所以,我們理解閉包的概念和作用。

var AUTHOR = 'tom';

return function () {

return AUTHOR;

}

})();

首先,我們要明白的閉包的概念:關于閉包的概念,眾說紛紜,概念本身就一致,各種書籍和網友的理解都是不同的。我根據自己的理解,就下個自己能理解的概念吧。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 閉包的概念

? ? ? ? 閉包 :是指有權訪問另一個函數作用域中的變量的函數。這個紅皮書下的定義。從這個定義上看,閉包是函數,這個函數可以訪問另一個函數作用域的變量,也就是說,是兩個函數組成閉包結構。創建閉包的常見方式是在一個函數里創建另一個函數。也就是分為外層函數和內層函數。外層函數返回的是,持有外層函數的變量的內層函數。

? ? ? 要理解閉包的概念,就要從作用域來進行分析,內層函數可以通過作用域鏈來訪問外層的變量,我們可以說持有。當內層函數持有外層函數的變量時,又被外層函數返回了(注意: 可以用return 關鍵字,也可以使用掛載在對象屬性上,不一定要使用return關鍵字來返回。)這個持有的變量。從外層函數中,返回了內層函數的持有的變量,返回到了那里去了呢?也就是說,是哪個對象接受了這個返回?這個也是我們要考慮的,比如說,

? function outer () {

? ? ?var name = 'tom'

? ? ? return function inner () {

? ? ? ? ? ? ? console.log(name)

? ? ?};

};

var fn = outer();

fn();

內層函數是持有外層函數的變量name,外層函數用return關鍵字來進行返回,返回到outer函數外面,也是就說,是outer函數外層的對象接受了這個返回,從代碼上看,是window對象可以進行接受。所以,我們可以通過window對象可以拿到這個值。也就是要向外面提供接口,可以訪問某些數據。 返回的用法不一定要用return 關鍵字來進行的,可以用對象的屬性也可以進行返回。比如:

(function(){

? ? ? var name = 'xuyinghao';

? ? ? window.getValue = function () {

? ? ? ? ?return name;

? ? ? ?}

})();?

這樣,通過掛載在window對象的getValue屬性上,我們可以通過window.getValue()屬性上進行拿到值。

所以,返回的方法也是很多的,掛載在對象上的屬性上也是可以訪問到值。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?閉包的作用


閉包的作用:

第一:可以在全局作用域環境下,可以訪問局部變量和局部環境的相關操作。

第二:讓相關的局部變量保存到獨立的內存空間。長期保持長久,需要的時候,我們可以拿來用。

第三 : 可以使用閉包創建塊級作用域,也就是說,可以用閉包創建常量,這樣,我們要遇見的是購物車的價格,或者是其他的需求,就可以用,閉包來進行創建變量。

var getAuthor = (function (){

var AUTHOR = 'tom';

return function () {

return AUTHOR;

}

})();

第四個方法:可以用閉包來進行開辟獨立的命名空間,這樣,就可以避免空間命名沖突。在獨立的空間中,我們可以用來保護數據,也不會污染全局的變量,但是,局部的變量的是無法被外部訪問到的,我們可以通過閉包也可以給外部開放接口,提供接口,外部的可以通過接口,可以訪問或者是引用內部的數據。閉包可以在內部的加工,處理一些邏輯業務,在返回給外部使用的。

第五個方法:是可以通過中間層來進行作用鏈的變量訪問,來進行保存我們需要的不可控的變量。一些數據是不可控的,我們可以通過閉包中間層,來進行按照我們的需要的邏輯來進行保存我們的數據。比如是for循環,添加 對應的下標,我們可以通過閉包來進行加個中間層,通過傳參值拷貝,來進行保存的是我們要進行需要的對應的下標。

那么,閉包的運行原理是什么呢?

也是引用型的數據類型。匿名函數的概念。我們也可以再來復習一下。匿名函數是沒有具體的函數名,其他的結構和函數類型一樣。匿名函數沒有函數名,這樣,我們就帶來調用函數的一些麻煩。因為,我們在調用函數時,是通過函數名來加上();來調用函數執行。一旦用函數名+()的形式來調用函數時,函數會立即執行。也就是頁面一旦加載時,就執行了。這個執行順序是我們首要關注的。但是匿名函數沒有函數名,就不能通過常規的函數調用方法來調用匿名函數。我們在js低級階段時,我們經常用事件驅動來調用匿名函數。還有用匿名函數來作為參數。比如是setInterval setTimeout ,還有一些數組的方法也是用匿名函數來作為參數。我們要清楚的明白調用函數的原理。函數名是具體的指定當前函數存放的地址。所以,我們可以用一個變量來保存函數名的地址。然后用變量加()來調用匿名函數。比如 : var ints = function () { ??

? ? ? ? ? ? ? ? ? ? alert("hello word");

};

ints (); ?// 這樣就可以調用匿名函數了。

還有一個比較常用的方法:匿名函數自調用。就是匿名函數自己調用自己。因為我們可以通過調用的原理來自己可以調用自己。比如:

// 我們來創建一個匿名函數

? (function () { ?

? ? ? ?alert("hello word")

?}) (); // 這就是匿名函數自己調用函數的形式。用一個括號來包括自己,形成函數名。然后再加個括號,來表示調用。符合調用函數的原理。這就是我們的思想。

閉包是借助匿名函數來實現我們需要的功能的。形成塊級化的模擬效果。來提高我們的代碼的優化。閉包是自己作為某一個函數的返回值,然后可以通過用一個變量來保存這個函數的值。再調用變量的值,就可以拿到閉包的局部變量。當然,我們要訪問的局部變量用閉包來包括。這是閉包的原理。因為閉包的形千變萬化,我們只有通過原理來實現閉包的功能。因為是全局作用域來實現訪問局部變量,也就是說,把值返回去就可以。形式可為是千變萬化,有事件驅動的,就可以直接來在全局作用域來實現。總之,要根據原理來實現的。來觀察閉包的結構的。我們在閉包學習時,對for循環的理解更加深一步。for循環的要素就是在頁面加載時候,就循環加載完了,在對每個循環的要素時,添加事件驅動時,我們就難免下標的循環會產生統一的下標,無法實現每個下標的處理事件。就是因為for循環的變量是全局變量。for循環的括號內的變量是全局變量,在循環外可以被訪問。等我們點擊的時刻,就已經加載完了。訪問的下標就是最后變量i的值。這個是非常重要的。而且是,for 循環的中的循環變量最后已經改變了。而且是全局變量,可以在全局作用域來訪問。最后的循環變量值等于length的值。在循環變量-1時,我們的循環操作是終止的。我們可以在這個基礎上,我們可以通過閉包和for循環結合在一起,編譯器中我們可以看看。

我們可以利用循環來進行重復的操作,應用這循環,就是讓我們提高效率。因為計算機處理起來是以毫秒的速度來加載。我們經常用for循環來進行遍歷數據來進行操作。不僅是for循環,只要是循環,加載的速度就以毫米的來加載的,這是我們需要的;循環就是解決我們重復的事情。在這里,我們補充一些for循環的知識。

我們可以利用閉包和循環來進行操作。閉包可以來開辟空間保存每一次循環的值。這樣就可以保證下標的正確訪問。開辟空間保存值。這樣,達到我們的目的。閉包的原理就是這樣的。來訪問這樣的局部的變量成為全局變量。訪問的時候,我們可以關聯來去訪問,不能像我們平常這樣的去訪問全局的變量。需要我們來關聯去訪問。比如,經典的案例的訪問就是這樣的。先保存這樣的一個值,然后再去訪問這樣的值。才能關聯起來的。我們才能達到我們的目的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容