MDN對(duì)閉包的定義為:閉包是指那些能夠訪問(wèn)自由變量的函數(shù)彩郊。
自由變量 是指在函數(shù)中使用的蚪缀,但既不是函數(shù)參數(shù)(形參)也不是函數(shù)的局部變量的變量秫逝。
ECMAScript中询枚,閉包指的是:
從理論角度:所有的函數(shù)。因?yàn)樗鼈兌荚趧?chuàng)建的時(shí)候就將上層上下文的數(shù)據(jù)保存起來(lái)了金蜀。哪怕是簡(jiǎn)單的全局變量也是如此的畴,因?yàn)楹瘮?shù)中訪問(wèn)全局變量就相當(dāng)于是在訪問(wèn)自由變量尝胆,這個(gè)時(shí)候使用最外層的作用域。
從實(shí)踐角度:
以下情況的函數(shù)才算是閉包:
- 即使創(chuàng)建它的上下文已經(jīng)銷(xiāo)毀含衔,它仍然存在(比如,內(nèi)部函數(shù)從父函數(shù)中返回)
- 在代碼中引用了自由變量
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
f 執(zhí)行上下文維護(hù)了一個(gè)作用域鏈
fContext = {
Scope: [AO, checkscopeContext.AO, globalContext.VO],
}
就是因?yàn)檫@個(gè)作用域鏈缓呛,f 函數(shù)依然可以讀取到 checkscopeContext.AO 的值杭隙,說(shuō)明當(dāng) f 函數(shù)引用了 checkscopeContext.AO 中的值的時(shí)候哟绊,即使 checkscopeContext 被銷(xiāo)毀了寺渗,但是 JavaScript 依然會(huì)讓 checkscopeContext.AO 活在內(nèi)存中,f 函數(shù)依然可以通過(guò) f 函數(shù)的作用域鏈找到它信殊,正是因?yàn)?JavaScript 做到了這一點(diǎn),從而實(shí)現(xiàn)了閉包這個(gè)概念.
從執(zhí)行上下文去思考它們的差異
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = (function (i) {
return function(){
console.log(i);
}
})(i);
}
data[0]();
data[1]();
data[2]();