我一般都是说,创建一个动态存储空间,突破作用域的限制。让外部可以访问内部的变量,感觉自己答得没什么问题啊,为什么面试完没通知?
巴扎黑2017-04-17 13:03:28
其實閉包沒有那麼高深複雜。
僅從規範的角度:
function a() {
var x = 1, y = 2;
return function b() {
console.log(x + y);
}
}
var f = a();
f();
在執行a
期間,我們可以認為它的局部變數存放在一個內部物件Env
裡面,a
的執行環境保存了Env
的引用。
定義b
的時候,b
也會儲存對Env
的引用。
在a
返回時,a
的執行環境被銷毀,它對Env
的引用也就沒有了。但是,只要b
還可以存取(例如,a
透過回傳值回傳了b
)。那麼b
對Env
的引用仍然存在,它仍然可以存取Env
中保存的局部變數。
將來在函數b
執行期間,可以透過所謂的作用域鏈存取x
和y
。
這就是閉包。
用圖表示就是:
在函數a
回傳前:
在函數a
回傳後:
天蓬老师2017-04-17 13:03:28
你爸生了你這個兒子,你有可以自己賺錢,也可以使用你爸的錢,但是,你不想讓你爸使用你的錢。
映射到js中。
A函數巢狀B函數,B函數中的變數只能在B函數所產生的作用域中使用,A函數無法使用B函數的變數。但是B可以使用A,和全域作用域的變數。
黄舟2017-04-17 13:03:28
就是引用了外部變數的內部函數。
順便貼下自己以前寫的文章
http://scarletsky.github.io/2015/12/02/the-little-javascript-closures/
大家讲道理2017-04-17 13:03:28
閉包就是泛函。
R語言不服JS。
a <-function () {
x = 1
y = 2
b <- function(){print(x + y)}
return(b)
}
a()()
>[1] 3
怪我咯2017-04-17 13:03:28
帳號裡面的錢就是閉包,這是我能想到的對普通人的解釋了...除了帳號擁有者(呼叫者)和銀行(記憶體控制器)之外,誰也不知道裡面到底有沒有錢,雖然帳號相關的東西是暴露的(例如銀行卡,但存摺不符合要求)
高洛峰2017-04-17 13:03:28
前不久我面試也遇到這個問題
閉包是指有權限存取另一個作用域中變數的函數。
一般,函數在執行完後會立刻釋放記憶體。但是,有時候我們需要在希望函數每次執行「記住」上一次的執行結果,而不是立即銷毀。通俗的說,閉包一般用來實現延長記憶力
大家讲道理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傳入匿名函數中.