昨天給一位朋友講解閉包伸蚯,講解過程中想到一種故事型的講解方式博秫,朋友聽了直呼內(nèi)行菇篡。
你說的這個朋友到底是不是...
首先看一段簡單到哭的代碼;
const funcA = function () {
const x = 1;
}
funcA();
console.log('x 是我得不到的人:', x);
由于 x 是 funcA 的局部變量思恐,作用域范圍在 funcA 函數(shù)內(nèi)部,外部的 console 無法訪問 x膊毁。
假如我一定要獲得局部變量 x 呢胀莹?那么可以通過:
const funcA = function () {
const x = 1;
return x; // 通過 return 讓 x 躲過被摧毀的命運
}
const x = funcA();
console.log('得到 x 了:', x);
但是上述實現(xiàn)沒有什么私密性可言,這樣方式豈不是讓所有人都可以隨意得到 x 了嗎婚温?如何能夠更加私密的得到 x 描焰?答案就是「閉包」。
一個故事
看一段悲傷到哭的故事:
// 一個溫馨的家
const home = function () {
const child = 'L'; // 有一個名為 L 的孩子
const child_home = 'None'; // 孩子還沒有自己的家栅螟,沒有自己的保護殼
return child_home;
};
// child 隨著 home 的結(jié)束而被無情的摧毀
// 但還有一點希望:child_home 通過返回值「活下來」了
const alive = home();
// 但結(jié)局最終是悲傷的:child_home 里空空如也荆秦,只有一個冷冰冰的 None.
// child 沒能幸還
console.log('alive: ', alive);
一個溫馨的家保護著溫室里的花朵:一個正在成長中的孩子。但由于種種原因力图,這個溫馨的家不再溫馨步绸,「家」已經(jīng)結(jié)束了,那個孩子也被徹底摧毀了吃媒。
男淚女淚瓤介!救救孩子吧!
// 一個溫馨的家
const home = function () {
const child = 'L'; // 有一個名為 L 的孩子
// 內(nèi)心強大的孩子構(gòu)建了自己的家赘那!
// child_home 將 child 擁抱入懷中刑桑,
// 將它「封閉」在了自己的「包」中
// child_home 是 child 以及其他孩子們的新家
// 孩子給這個新家起名為「閉包」!
const child_home = function (check) {
const child_inner = child;
if (check == 'child, it\'s me!') return child_inner;
}
// return 將為這個新家 child_home 開啟一個避難通道募舟!
// 在 home 摧毀時
// child_home 這個「閉包」完整的保護著新家的環(huán)境(函數(shù)上下文)
// child_home 帶著孩子們(局部變量)逃離了災難現(xiàn)場祠斧!
return child_home;
};
// home 結(jié)束
// 但 child_home 通過返回值「活下來」了
const alive = home();
// child 也活下來了!
// 而且把自己保護的很好胃珍,需要人臉識別梁肿,才能家訪!
console.log('alive: ', alive('child, it\'s me!'));
孩子最終成長到內(nèi)心足夠強大觅彰,構(gòu)建了自己的新家吩蔑,新家把自己保護起來,形成一個「閉包」填抬,在原始家庭結(jié)束的時候逃離了災難現(xiàn)場烛芬。同時如果有需要,還能把自己保護的很好,即使逃離后也不是任何人都能訪問赘娄。
救出孩子了仆潮!男笑女笑!
總結(jié)
從上面可以知道「閉包」能夠?qū)崿F(xiàn)的兩個核心點:
- 詞法作用域遣臼。即 home 函數(shù)內(nèi)定義的 child_home 函數(shù)性置,能夠按照代碼書寫的順序,訪問到 home 函數(shù)內(nèi)部且在 child_home 之前定義的變量揍堰。因為詞法作用域的存在鹏浅,child_home 才能把 child 變量封閉保護起來。
- 函數(shù)作為值傳遞屏歹。由于函數(shù)作為一等公民隐砸,可以像變量一樣被賦值,可以作為值傳遞蝙眶,也可以作為返回值返回季希,所以才能讓函數(shù)這個「閉包」順利逃離災難現(xiàn)場,逃離被摧毀的命運幽纷。
汪
汪