javascript閉包詳解及代碼實例

什麼是閉包,從事前端兩年卻沒有去瞭解這些基礎的知識,閉包對於學JavaScript的人來說是很重要的一個知識點,但是究竟什麼是閉包呢?閉包是指有權訪問另一個函數作用域中的變量的函數。常見的方法就是在一個函數內部創建另一個函數。

變量


變量按作用域分為兩種,全局變量和局部變量,在函數中,全局變量可以直接被使用,但是在全局環境中,函數內部定義的局部變量卻無法被直接使用。(註:在定義局部變量時一定要使用var,否則會將該變量定義成全局變量,不要因此而誤會局部變量可以在全局使用)。

全局變量:

var a = 100;
function f1(){
    console.log(a);
}
f1();           //100

局部變量:

function f1(){
    var a = 200;
}
f1();
console.log(a); //出錯,如果你先在瀏覽器上運行過上面全局變量的代碼,那麼結果會顯示100。

函數中的全局變量:

function f1(){
    a = 999;
}
f1();
console.log(a); //999,因為a已經是全局變量,所以在函數外可以直接獲得

閉包


先看一下下面的代碼:

function f1(){
var n = 1;

function f2(){
    console.log(n);
    }

return f2;
}

var result = f1();
result();           //1

函數f2中的代碼就是閉包,閉包就是能夠讀取其他函數內部變量的函數。由於在Javascript語言中,隻有函數內部的子函數才能讀取局部變量,因此可以把閉包簡單理解成”定義在一個函數內部的函數”。所以,在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。
閉包的用途有兩個,一個是前面的在另一個函數中調用函數變量,另一個作用是會使函數中的這些變量值始終保存在內存中,可以持續使用,這也是閉包的一個問題,就是太占用內存,也會導致內存泄漏。

function f1(){
var n = 999;

nAdd = function(){
    n +=1;
};
function f2(){
    console.log(n);
}

return f2;
}

var result = f1();
result();           //999
nAdd();
result();           //1000,從這裡可以看出函數中的局部變量並沒有因為函數調用結束後回收。

閉包中的this對象


在閉包中使用this對象可能會導致一些問題,this本身在運行時基於函數的執行環境,即作用域。在全局函數中,this指向widow,在函數被當做某個對象的方法調用時,this指向那個對象。不過,匿名函數的執行環境具有全局性,因此this會指向window。

var name = "The Window";

var object = {
    name:"My Object",

    getNameFunc:function(){
        return function(){
            return this.name;
        };
    }
};

console.log(object.getNameFunc()());        //The Window

所以我們在閉包中使用匿名函數時,我們需要在定義匿名函數前將this的對象賦給其他對象,然後在匿名函數中調用這個對象,就能避免這個問題。

var name = "The Window";

var object = {
    name:"My Object",

    getNameFunc:function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};

console.log(object.getNameFunc()());        //My Object

You May Also Like