再讀閉包

鬧鬧不愛鬧發表於2019-03-12

前言

每次被問什麼是閉包時,有以下答案:

1. 函式內返回一個函式。

2. 可以訪問私有變數的函式。

。。。

但是,看著上面的答案,其實我還是一臉懵逼了,以至於再問到閉包在工作中的作用時,我是這麼回答的:

其實也沒啥吊用。。

其實如果你能真正描述出什麼是閉包時,你也能夠想到閉包的作用。那麼什麼是閉包:

閉包是由函式和建立該函式的詞法環境組成的。這個詞法環境包含了該函式被建立時可以訪問的所有區域性變數。

還是一臉懵逼?簡潔一點就是:

閉包 = 函式 + 該函式可以訪問的一個物件。

舉個例子:

function parentScope() {
    var name = '父親';
    return function() {
        console.log(name)
    }
}
var Closures = parentScope();

Closures變數是parentScope返回的匿名函式的引用,而這個匿名函式是在parentScope函式內部宣告的,可以訪問parentScope
下的區域性變數(name)。所以Closures = 匿名函式 + 匿名函式可以訪問的詞法環境。所以Closures就是一個閉包。複製程式碼

知道了什麼是閉包,那閉包到底有什麼用呢?其實從上面認識閉包可以得出:

1. 通過閉包可以在函式外部訪問函式作用域內的區域性變數。

那除了這個作用,還有其他作用嗎?

實現js的模組化(module pattern)。webpack實現的模組化就是利用了閉包:

// module1.js
function (module, module.exports) {
    var private = 'jack';
    module.exports = {
        getPrivate() {
            return private;
        }
    }
    return module.exports;
}複製程式碼

webpack通過將我們的業務程式碼用一個函式包裹,並且傳入module.exports物件,使其他模組可以使用這個模組的方法,進而訪問到這個模組的私有變數。想一想,我們平時怎麼用模組的:

var m = require('module1.js'); // 此時m就是上面匯出的module.exports物件
m.getPrivate() // 返回module1中的私有變數。複製程式碼

所以,通過閉包,即實現了私有變數,又可以通過閉包來實現模組化。


相關文章