js中閉包的理解以及存在的意義


1、閉包就是指有權訪問另一個函數作用域中的變量的函數,這句話有兩個點,1閉包是函數,2作用域。

有了這兩個條件我們能聯想到的就是js的執行環境。函數的執行環境依賴於變量作用域,在js中這個作用域是函數定義時決定的,而不取決於調用時。通過如下案例來解釋:

    var a = 'hello'      //全局變量
    function fun() {
        var a = 'world'   //局部變量
        function fn() {
            return a
        }
        return fn()
    }
    console.log(fun())      //world
    var a = 'hello'
    function fun() {
        var a = 'world'
        function fn() {
            return a
        }
        return fn
    }
    console.log(fun()()) //world
 //函數fun返回值fn,fn執行過程中取得a的值為fn定義時的值,而並非取得全局變量

如果按照正常的說法,函數在執行完畢后,其內部相關的作用域鏈會被回收,而閉包恰巧就是鑽了空子,使得函數中的作用域鏈再次其內部的變量不被銷毀,所以在有些場合,尤其是循環操作DOM的過程中,過度的使用閉包,可能會造成內存泄漏。

2、通過上面的案例,我們認識到,閉包就相當於一個塊,這個塊里包含所定義時的作用域。現在嘗試用閉包寫一個計數器
function sum() {
        var a = 3  //私有變量
        return {
            add: function(k) {
                return a + k
            },
            del: function(k) {
                return k - a
            }
        }
    }
    var i = sum()
    var j = sum()
    console.log(i.add(1))  //4
    console.log(j.add(3))  //6
    console.log(i.del(9))  //6
    console.log(j.del(6))  //3

我們開始定義了個sum函數,返回兩個add和del函數形成閉包,在對其兩個函數進行分別操作時,發現i,j變量分別控制的是不同的兩個結果,這就表明,兩個方法 都可以訪問私有變量 a 而每次調用add都回創建一個新的作用域鏈和一個新的私有變量,可以多次重復使用,不會影響到彼此。但是兩者都僅僅局限sum函數創建下,現在對其進行改造寫法:如下:

    (function(w) {
        var a = 3
        this.add = function(k) {
            return a + k
        }
        this.del = function(k) {
            return k - a 
        }
    }(window))
    console.log(add(1))  //4
    console.log(add(3))  //6
    console.log(del(9))  //6
    console.log(del(6)) //3 

結果和上述一致,區別在於被調用的對象有不同,我們通過一個匿名函數來把我們要執行的函數添加到window對象上,來達到全局變量的目的, 我們可以這樣理解,一個匿名函數就相當於一個大的作用域,而內部的變量每次都只能在內部調用,其他外界函數是訪問不到的,這樣就保證了一個獨立的作用域鏈.

3、總結閉包的優缺點

  * 優點 1、使用閉包可以通過外部函數訪問內部的函數值,提升作用域,便於鏈式調用
  * 優點 2、內部的變量可以多次重復使用,不會造成全局的變量污染。
  * 優點 3、全局變量可能會造成命名沖突,使用閉包不用擔心這個問題,因為它是私有化,加強了封裝性,有效防止了
  * 缺點 1、閉包創建的變量都被保存在內存中,內存消耗很大,處理不當,IE中容易造成內存泄漏。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM