一劣纲、什么是閉包击碗?##
簡(jiǎn)言之筑悴,閉包是由函數(shù)引用其周邊狀態(tài)(詞法環(huán)境)綁在一起形成的(封裝)組合結(jié)構(gòu)。在 JavaScript 中延都,閉包在每個(gè)函數(shù)被創(chuàng)建時(shí)形成雷猪。
這是基本原理,但為什么我們關(guān)心這些晰房?實(shí)際上求摇,由于閉包與它的詞法環(huán)境綁在一起,因此閉包讓我們能夠從一個(gè)函數(shù)內(nèi)部訪問(wèn)其外部函數(shù)的作用域殊者。
閉包的形成需要兩個(gè)條件:
- 在函數(shù)內(nèi)部創(chuàng)建新的函數(shù)与境;
- 新的函數(shù)在執(zhí)行時(shí),訪問(wèn)了函數(shù)的變量對(duì)象猖吴;
要使用閉包摔刁,只需要簡(jiǎn)單地將一個(gè)函數(shù)定義在另一個(gè)函數(shù)內(nèi)部,并將它暴露出來(lái)海蔽。要暴露一個(gè)函數(shù)共屈,可以將它返回或者傳給其他函數(shù)绑谣。
內(nèi)部函數(shù)將能夠訪問(wèn)到外部函數(shù)作用域中的變量,即使外部函數(shù)已經(jīng)執(zhí)行完畢拗引。
根據(jù)以上的摸索情況借宵,再次總結(jié)一下閉包:
- 閉包是在函數(shù)被調(diào)用執(zhí)行的時(shí)候才被確認(rèn)創(chuàng)建的。
- 閉包的形成矾削,與作用域鏈的訪問(wèn)順序有直接關(guān)系壤玫。
- 只有內(nèi)部函數(shù)訪問(wèn)了上層作用域鏈中的變量對(duì)象時(shí),才會(huì)形成閉包哼凯,因此欲间,我們可以利用閉包來(lái)訪問(wèn)函數(shù)內(nèi)部的變量。
閉包使用的例子####
閉包的用途之一是實(shí)現(xiàn)對(duì)象的私有數(shù)據(jù)断部。數(shù)據(jù)私有是讓我們能夠面向接口編程而不是面向?qū)崿F(xiàn)編程的基礎(chǔ)猎贴。而面向接口編程是一個(gè)重要的概念,有助于我們創(chuàng)建更加健壯的軟件家坎,因?yàn)閷?shí)現(xiàn)細(xì)節(jié)比接口約定相對(duì)來(lái)說(shuō)更加容易被改變嘱能。
“面向接口編程,別面向?qū)崿F(xiàn)編程虱疏∪锹睿” 設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖囊?/a>
在 JavaScript 中,閉包是用來(lái)實(shí)現(xiàn)數(shù)據(jù)私有的原生機(jī)制做瞪。當(dāng)你使用閉包來(lái)實(shí)現(xiàn)數(shù)據(jù)私有時(shí)对粪,被封裝的變量只能在閉包容器函數(shù)作用域中使用。你無(wú)法繞過(guò)對(duì)象被授權(quán)的方法在外部訪問(wèn)這些數(shù)據(jù)装蓬。在 JavaScript 中著拭,任何定義在閉包作用域下的公開(kāi)方法才可以訪問(wèn)這些數(shù)據(jù)。例如:
在上面的例子里牍帚,get() 方法定義在 getSecret() 作用域下儡遮,這讓它可以訪問(wèn)任何 getSecret() 中的變量,于是它就是一個(gè)被授權(quán)的方法暗赶。在這個(gè)例子里鄙币,它可以訪問(wèn)參數(shù) secret。
對(duì)象不是唯一的產(chǎn)生私有數(shù)據(jù)的方式蹂随。閉包還可以被用來(lái)創(chuàng)建有狀態(tài)的函數(shù)十嘿,這些函數(shù)的執(zhí)行過(guò)程可能由它們自身的內(nèi)部狀態(tài)所決定。
在函數(shù)式編程中岳锁,閉包經(jīng)常用于偏函數(shù)應(yīng)用和柯里化绩衷。為了說(shuō)明這個(gè),我們先定義一些概念:
函數(shù)應(yīng)用:一個(gè)過(guò)程,指將參數(shù)傳給一個(gè)函數(shù)咳燕,并獲得它的返回值勿决。
偏函數(shù)應(yīng)用:一個(gè)過(guò)程,它傳給某個(gè)函數(shù)其中一部分參數(shù)招盲,然后返回一個(gè)新的函數(shù)剥险,該函數(shù)等待接受后續(xù)參數(shù)。換句話說(shuō)宪肖,偏函數(shù)應(yīng)用是一個(gè)函數(shù),它接受另一個(gè)函數(shù)為參數(shù)健爬,這個(gè)作為參數(shù)的函數(shù)本身接受多個(gè)參數(shù)控乾,它返回一個(gè)函數(shù),這個(gè)函數(shù)與它的參數(shù)函數(shù)相比娜遵,接受更少的參數(shù)蜕衡。偏函數(shù)應(yīng)用提前賦予一部分參數(shù),而返回的函數(shù)則等待調(diào)用時(shí)傳入剩余的參數(shù)设拟。偏函數(shù)應(yīng)用通過(guò)閉包作用域來(lái)提前賦予參數(shù)慨仿。
** 題1**
function fun(n,o) {
alert(o)
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3); //undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3); //undefined,0,1,1
var c = fun(0).fun(1); c.fun(2); c.fun(3); //undefined,0,1,1
題2
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //The Window
題3
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());//My Object