1. 程式人生 > >對js中區域性變數、全域性變數和閉包的理解

對js中區域性變數、全域性變數和閉包的理解

對js中區域性變數、全域性變數和閉包的理解

區域性變數

對於區域性變數,js給出的定義是這樣的:在 JavaScript函式內部宣告的變數(使用 var)是區域性變數,所以只能在函式內部訪問它。(該變數的作用域是區域性的)。可以在不同的函式中使用名稱相同的區域性變數,因為只有宣告過該變數的函式才能識別出該變數。只要函式執行完畢,本地變數就會被刪除。

我們先來逐步理解:

  • 只能在函式內部訪問

    function test() {
        var a = 0;
        return a;
    }
    
    console.log(a);
    //結果:a is not defined

    上面的程式碼聲明瞭一個test()函式,在函式內部聲明瞭一個區域性變數a,當我們嘗試在函式外訪問區域性變數a時,出來的結果是a is not defined

    我們再來看下面這個例子:

    function test() {
        var a = 0;
        return a;
    }
    
    console.log(test());
    //結果:0

    以上兩個例子很好的闡述了局部變數只能在函式內部訪問,當呼叫函式時,函式域自動執行其中的程式碼,區域性變數自然也被呼叫。

  • 只要函式執行完畢,本地變數就會被刪除

    function b() {
        var y = 0;
        z = ++y;
        console.log("這是區域性變數y:",z)
        return z;
    }
    
    console.log(b(),b(),b());
    //結果:這是區域性變數y: 1
    //這是區域性變數y: 1
    //這是區域性變數y: 1
    //1 1 1

    從上面程式碼我們可以看出,我們執行了3次函式呼叫,得到的結果都是1,可能有人會說,這很簡單啊,每次出來的結果都是1,那是因為每次執行函式,函式內都會將區域性變數y初始化為0。沒錯,的確是這樣,但是如果不初始化變數,則得到的返回值是NaN,所以初始化是必要的。所以,無論用什麼辦法,在函式內部用一個區域性變數去做累加,是不可能實現的。但是,我們可以通過全域性變數和閉包來實現累加。

全域性變數

在js中,這樣定義全域性變數, 在函式外宣告的變數是全域性變數,網頁上的所有指令碼和函式都能訪問它。 全域性變數會在頁面關閉後被刪除。

  • 我們再來看一個例子

    var a = 0;
    
    function b() {
        ++a;
        console.log("這是全域性變數a",a);
        return a;
    }
    console.log("這是未改變的全域性變數a:",a,"這是函式b():",b(),b(),b(),"這是改變後的全域性變數a:",a);
    //結果:這是全域性變數a 1
    //這是全域性變數a 2
    //這是全域性變數a 3
    //這是未改變的全域性變數a: 0 這是函式b(): 1 2 3 這是改變後的全域性變數a: 3

    上面程式碼定義了一個全域性變數a,和一個b()函式,通過函式內部對a執行自加加,實現了累加目的,通過三次呼叫函式,得到的結果a為3。

閉包

什麼是閉包呢?閉包的定義是這樣的,閉包是一種保護私有變數的機制,在函式執行時形成私有的作用域,保護裡面的私有變數不受外界干擾。直觀的說就是形成一個不銷燬的棧環境。

我對閉包的理解是這樣的,閉包就是一個內嵌函式引用頂層函式的變數,而頂層函式是一個立即執行函式(自呼叫函式),因為它會自動呼叫,所以區域性變數不會被刪除,但是這會增加記憶體消耗。

  • 來看一個例子

    function a() {
        var b = 0;
        return function() {
            return ++b;
        }
    }
    
    var closure = a();
    console.log("這是閉包:",closure(),closure(),closure());
    //結果:這是閉包: 1 2 3

    我們看到,由於閉包的特殊機制,使得區域性變數在函式執行完之後不會被銷燬,由此得到的最後結果為3 ,而不是1。