1. 程式人生 > 程式設計 >詳解JavaScript閉包問題

詳解JavaScript閉包問題

閉包是純函式式語言的傳統特性之一。通過將閉包視為核心語言構件的組成部分,語言展示了其與函數語言程式設計語言的緊密聯絡。由於能夠簡化複雜的操作,閉包在主流Script庫以及高水平產品程式碼中日益流行起來。

一、變數的作用域

在介紹閉包之前,我們先理解JavaScript的變數作用域。變數的作用域分為兩種:全域性變數和區域性變數。

1、全域性變數

var n = 999; //全域性變數

    function f1() {
        a = 100; //在這裡a也是全域性變數
        alert(n);
    }
    console.log(a); //100

在這裡,函式內外部可以直接取到變數的值——全域性變數

2、區域性變數

//區域性變數
    function f2() {
        var b = 22;
    }
    console.log(b);   //報錯

在這裡,函式外部無法直接取到函式內部定義的值——區域性變數

講到這裡,當我們想要從外部取到區域性變數的值,這時候該怎麼辦呢?
請接著往下看:

二、如何從外部獲取區域性變數

接下來我們看一個例子:

var outer = 'Outer'; // 全域性變數
var copy; 
function outerFn(){ // 全域性函式
 var inner = 'Inner'; // 該變數只有函式作用域,無法從外部訪問
 function innerFn(){ // outerFn()中的innerFn() 
 // 全域性上下文和外圍上下文都可以在這裡使用,
 // 因此可以訪問到outer和inner 
 console.log(outer); 
 console.log(inner); 
 } 
 copy=innerFn; // 儲存innerFn()的引用
 // 因為copy是在全域性上下文中宣告的,所以在外部可以使用
} 
outerFn(); 
copy(); // 不能直接呼叫innerFn(),但是可以通過在全域性作用域中宣告的變數來呼叫

來分析一下上面的例子。在innerFn()中可以訪問變數outewww.cppcns.comr,因為它處於全域性上下文中。

在執行完outerFn()之後,執行了innerFn(),這是通過將該函式的引用複製到一個全域性變數
copy中來實現的。在利用變數copy呼叫函式innerFn()執行時,此刻已經不在outerFn()的作
用域中了。因此下面的程式碼不是應該失敗嗎?
console.log(inner);
變數inner的值應該是undefined吧?可是,上面程式碼片段的輸出卻是:
“Ou程式設計客棧ter”
“Inner”

這就是JavaScript的鏈式作用域結構,子對http://www.cppcns.com

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

這樣我們就可以獲取到函式內部的區域性變量了。

三、閉包的概念

上面程式碼塊中的copy()函式就是閉包。在我的理解,閉包就是能夠讀取到函式內部變數的函式。
而在JavaScript中,可http://www.cppcns.com以通過函式內部的子函式獲取到區域性變數,因此可以把閉包理解為定義在函式內部的函式。
可以把它理解為一個將函式內部和外部連線起來的橋樑。

四、閉包的作用

在我看來,閉包的作用主要體現在兩個方面:

1、可以讀取函式內部的變數

這個作用在上個程式碼塊已經表現得很清楚。

2、可以將區域性變數的值一直儲存在記憶體中

總所周知,區域性變數只有當使用的時候才會在記憶體中開闢出暫時的儲存空間,在函式執行結束後會自動釋放空間。而閉包的出現可以使得區域性變數可以像全域性變數一樣一致儲存在記憶體中。

        function c1() {
            var z = 9999;
            nAdd = function() {
                z += 1;
            }

            function c2() {
                console.log(z);
            }
            return c2;
        }
        var result = c1();
        result(); //9999
        nAdd();
        result(); //10000

在上述程式碼中,先執行一次c1(),此時z=9999;再執行一次nAdd(),使z+1;在執行一次c1()輸出此時z的值,z=10000。說明z的值一直儲存在記憶體中,並沒有在第一次呼叫c1()後背自動消除。

此時就要注意,閉包的使用會消耗很大的記憶體,不要濫用閉包。在退出函式之前,將不使用的區域性變數全部刪除。

到此這篇關於詳解JavaScript閉包問題的文章就介紹到這了,更多相關JavaScript閉包問題內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!