首頁  >  問答  >  主體

html5 - 用普通人能听懂的话回答什么是闭包

我一般都是说,创建一个动态存储空间,突破作用域的限制。让外部可以访问内部的变量,感觉自己答得没什么问题啊,为什么面试完没通知?

ringa_leeringa_lee2742 天前1342

全部回覆(13)我來回復

  • 巴扎黑

    巴扎黑2017-04-17 13:03:28

    其實閉包沒有那麼高深複雜。

    僅從規範的角度:

    function a() {
        var x = 1, y = 2;
        return function b() {
            console.log(x + y);
        }
    }
    
    var f = a();
    f();
    1. 在執行a期間,我們可以認為它的局部變數存放在一個內部物件Env裡面,a的執行環境保存了Env的引用。

    2. 定義b的時候,b也會儲存對Env的引用。

    3. a返回時,a的執行環境被銷毀,它對Env的引用也就沒有了。但是,只要b還可以存取(例如,a透過回傳值回傳了b)。那麼bEnv的引用仍然存在,它仍然可以存取Env中保存的局部變數。

    4. 將來在函數b執行期間,可以透過所謂的作用域鏈存取xy

    這就是閉包

    用圖表示就是:

    • 在函數a回傳前:

    • 在函數a回傳後:

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:03:28

    這回答逼格這麼高,沒收到通知一定是面試的單位效率不夠高

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 13:03:28

    你爸生了你這個兒子,你有可以自己賺錢,也可以使用你爸的錢,但是,你不想讓你爸使用你的錢。

    映射到js中。
    A函數巢狀B函數,B函數中的變數只能在B函數所產生的作用域中使用,A函數無法使用B函數的變數。但是B可以使用A,和全域作用域的變數。

    回覆
    0
  • 黄舟

    黄舟2017-04-17 13:03:28

    就是引用了外部變數的內部函數。

    順便貼下自己以前寫的文章
    http://scarletsky.github.io/2015/12/02/the-little-javascript-closures/

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-17 13:03:28

    閉包就是泛函。

    R語言不服JS。

    a <-function () {
         x = 1
         y = 2
         b <- function(){print(x + y)}
        return(b) 
    }
    
    a()()
    
    >[1] 3

    回覆
    0
  • 黄舟

    黄舟2017-04-17 13:03:28

    一個函數存取了它的外部變數就是閉包

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 13:03:28

    可呼叫物件(callable object)。

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 13:03:28

    帳號裡面的錢就是閉包,這是我能想到的對普通人的解釋了...除了帳號擁有者(呼叫者)和銀行(記憶體控制器)之外,誰也不知道裡面到底有沒有錢,雖然帳號相關的東西是暴露的(例如銀行卡,但存摺不符合要求)

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 13:03:28

    前不久我面試也遇到這個問題

    閉包是指有權限存取另一個作用域中變數的函數。
    一般,函數在執行完後會立刻釋放記憶體。但是,有時候我們需要在希望函數每次執行「記住」上一次的執行結果,而不是立即銷毀。通俗的說,閉包一般用來實現延長記憶力

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-17 13:03:28

    網路上看到的:
    閉包其實就是函數的巢狀,內層的函數可以使用外層函數的所有變數,即使外層函數已經執行完畢.

    function checkClosure() { //外层函数
        var str = 'China'; //局部变量
        setTimeout(
            function() { console.log(str); } //这是一个匿名函数,可以调用外层函数的变量str
        , 2000);
    }
    checkClosure();
    console.log('Hello'); //先显示Hello,2秒后显示China.

    function裡用var聲明的局部變數在函數執行完就釋放了,function外的聲明的是全局變數,會一直常駐記憶體.checkClosure函數的執行是瞬間的,在checkClosure的函數體內創建了一個局部變數str,checkClosure執行完畢之後str並沒有被釋放,因為setTimeout內的匿名函數存在這對str的引用.待到2秒後函數體內的匿名函數被執行完畢,str才被釋放.

    又例如PHP在請求結束時,關閉資料庫連線:

    $db = new mysqli('127.0.0.1','user','pass','dbname',3306);
    register_shutdown_function(function() use ($db) {
        $db->close();
    });

    其中資料庫連接$db是匿名函數function()外的變數,PHP跟JS不同之處在於PHP需要使用use明確宣告把變數$db傳入匿名函數中.

    回覆
    0
  • 取消回覆