閉包就是一個(gè)函數(shù)把外部的那些不屬于自己的對(duì)象也包含(閉合)進(jìn)來(lái)了邀桑。
JavaScript中的閉包疆栏,無(wú)非就是變量解析的過(guò)程蒋歌。
首先看一段話(huà):
每次定義一個(gè)函數(shù),都會(huì)產(chǎn)生一個(gè)作用域鏈(scope chain)灾部。當(dāng)JavaScript尋找變量varible時(shí)(這個(gè)過(guò)程稱(chēng)為變量解析),總會(huì)優(yōu)先在當(dāng)前作用域鏈的第一個(gè)對(duì)象中查找屬性varible 惯退,如果找到赌髓,則直接使用這個(gè)屬性;否則,繼續(xù)查找下一個(gè)對(duì)象的是否存在這個(gè)屬性锁蠕;這個(gè)過(guò)程會(huì)持續(xù)直至找到這個(gè)屬性或者最終未找到引發(fā)錯(cuò)誤為止夷野。
看個(gè)簡(jiǎn)單版的例子:
(function(){
??? varhello="hello,world";
??? functionwelcome(hi){
??????? alert(hi);??? //解析到作用域鏈的第一個(gè)對(duì)象的屬性
??????? alert(hello);??? //解析到作用域鏈的第二個(gè)對(duì)象的屬性
??? }
??? welcome("It's easy");
})();
運(yùn)行結(jié)果很簡(jiǎn)單,一個(gè)彈窗It's easy.一個(gè)彈窗hello,world荣倾。
分析過(guò)程如下:
對(duì)于函數(shù)welcome()悯搔,定義welcome的時(shí)候會(huì)產(chǎn)生一個(gè)作用域鏈對(duì)象,為了表示方便舌仍,記作scopechain妒貌。scopechain是個(gè)有順序的集合對(duì)象。
scopechain的第一個(gè)對(duì)象:為了方便表示記作sc1抡笼, sc1有若干屬性苏揣,引用本函數(shù)的參數(shù)和局部變量,如sc1.hi 推姻;
scopechain的第二個(gè)對(duì)象:為了方便表示記作sc2平匈,sc2有若干屬性,引用外層函數(shù)的參數(shù)和局部變量藏古,如sc2.hello增炭;
...
scopechain的最后一個(gè)對(duì)象:為了方便表示記作scn,scn引用的全局的執(zhí)行環(huán)境對(duì)象拧晕,也就是window對(duì)象隙姿!,如scn.eval()厂捞;
這里之所以可以彈出hello,world输玷,原因就是變量解析時(shí)在welcome函數(shù)作用域鏈的第一個(gè)對(duì)象上找不到hello屬性,然后就去第二個(gè)對(duì)象上找去了(結(jié)果還真找到了)靡馁。
所以欲鹏,JavaScript中的所謂的高大上的閉包其實(shí)很簡(jiǎn)單,根本上還是變量解析臭墨。而之所以可以實(shí)現(xiàn)赔嚎,還是因?yàn)樽兞拷馕鰰?huì)在作用域鏈中依次尋找對(duì)應(yīng)屬性的導(dǎo)致的。
參考:知乎用戶(hù)