Javascript閉包项阴、閉包應(yīng)用場(chǎng)景和實(shí)例

建議參考博客:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合。
這個(gè)環(huán)境包含了這個(gè)閉包創(chuàng)建時(shí)所能訪問(wèn)的所有局部變量笆包。
先看下使用場(chǎng)景环揽,就能懂閉包到底是什么,閉包能用來(lái)干嘛庵佣。
1.在函數(shù)外使用函數(shù)內(nèi)的變量

function init(){
    var name = "hello world";//name是一個(gè)被init創(chuàng)建的局部變量
    function sayName(){//sayName是一個(gè)內(nèi)部函數(shù)歉胶,閉包
        alert(name);//使用了父級(jí)函數(shù)聲明的變量name
    }
    sayName();
}
init();//"hello world"

sayName的alert語(yǔ)句彈出了“hello world”,成功的顯示了其父函數(shù)中聲明的name變量的值。
嵌套的函數(shù)可以訪問(wèn)其外部聲明的變量

2.將函數(shù)與其所操作的某些數(shù)據(jù)關(guān)聯(lián)起來(lái)巴粪,通常通今,你使用只有一個(gè)方法的對(duì)象的地方,都可以使用閉包
在 Web 中肛根,你想要這樣做的情況特別常見辫塌。大部分我們所寫的 JavaScript 代碼都是基于事件的 — 定義某種行為,然后將其添加到用戶觸發(fā)的事件之上(比如點(diǎn)擊或者按鍵)晶通。我們的代碼通常作為回調(diào):為響應(yīng)事件而執(zhí)行的函數(shù)璃氢。

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<style type="text/css">
    body {
      font-family: Helvetica, Arial, sans-serif;
      font-size: 12px;
    }
    h1 {
      font-size: 1.5em;
    }
    h2 {
      font-size: 1.2em;
    }
</style>
<body>
    <h1>hello world</h1>
    <h2>hello world</h2>
    <button id="a">12</button>
    <button id="b">18</button>
    <button id="c">22</button>
<script type="text/javascript">
    document.getElementById("a").onclick = setSize(12);
    document.getElementById("b").onclick = setSize(18);
    document.getElementById("c").onclick = setSize(22);
    function setSize(fontSize){
        return function(){
            document.body.style.fontSize = fontSize + 'px';
        }
    }

</script>
</body>
</html>

3.用閉包模擬私有方法
編程語(yǔ)言中,比如 Java狮辽,是支持將方法聲明為私有的一也,即它們只能被同一個(gè)類中的其它方法所調(diào)用。
而 JavaScript 沒(méi)有這種原生支持喉脖,但我們可以使用閉包來(lái)模擬私有方法椰苟。私有方法不僅僅有利于限制對(duì)代碼的訪問(wèn):還提供了管理全局命名空間的強(qiáng)大能力瑞躺,避免非核心的方法弄亂了代碼的公共接口部分玲销。
下面的示例展現(xiàn)了如何使用閉包來(lái)定義公共函數(shù),并令其可以訪問(wèn)私有函數(shù)和變量幢泼。
在之前的示例中题诵,每個(gè)閉包都有它自己的詞法環(huán)境洁仗;而這次我們只創(chuàng)建了一個(gè)詞法環(huán)境,為三個(gè)函數(shù)所共享:Counter.increment性锭,Counter.decrement 和 Counter.value赠潦。

該共享環(huán)境創(chuàng)建于一個(gè)立即執(zhí)行的匿名函數(shù)體內(nèi)。這個(gè)環(huán)境中包含兩個(gè)私有項(xiàng):名為 privateCounter 的變量和名為 changeBy 的函數(shù)草冈。這兩項(xiàng)都無(wú)法在這個(gè)匿名函數(shù)外部直接訪問(wèn)她奥。必須通過(guò)匿名函數(shù)返回的三個(gè)公共函數(shù)訪問(wèn)瓮增。

這三個(gè)公共函數(shù)是共享同一個(gè)環(huán)境的閉包。多虧 JavaScript 的詞法作用域哩俭,它們都可以訪問(wèn) privateCounter 變量和 changeBy 函數(shù)绷跑。

var makeCounter = function () {
        var privateCounter = 0;
        function changeBy(val){
            privateCounter += val;
        };
        return {
            increment: function(){
                changeBy(1);
            },
            decrement: function(){
                changeBy(-1);
            },
            value: function(){
                return privateCounter;
            }
        }
    };
    var Counter1 = makeCounter();
    var Counter2 = makeCounter();
    Counter1.increment();
    console.log(Counter1.value());//1
    console.log(Counter2.value());//0

請(qǐng)注意兩個(gè)計(jì)數(shù)器 counter1 和 counter2 是如何維護(hù)它們各自的獨(dú)立性的。每個(gè)閉包都是引用自己詞法作用域內(nèi)的變量 privateCounter 凡资。

每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí)砸捏,通過(guò)改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境讳苦。然而在一個(gè)閉包內(nèi)對(duì)變量的修改带膜,不會(huì)影響到另外一個(gè)閉包中的變量。

以這種方式使用閉包鸳谜,提供了許多與面向?qū)ο缶幊滔嚓P(guān)的好處 —— 特別是數(shù)據(jù)隱藏和封裝。

4.循環(huán)里的閉包
怎么才能實(shí)現(xiàn)輸出0-5呢

for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, 1000 * i);
}//55555
//方法一式廷,makeCallback函數(shù)為每一個(gè)回調(diào)創(chuàng)建一個(gè)新的詞法環(huán)境咐扭。
function makeCallback(i) {
     return function() {
        console.log(i)
      };
    }
    for(var i=0;i<10;i++){
        setTimeout(makeCallback(i),1000)
    }
//另一種方法使用了匿名閉包
for(var i=0;i<10;i++){
        (function(i){
            setTimeout(function () {
                console.log(i)
            },1000)
        })(i)
    }
//使用let聲明變量
for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, 1000 * i);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市滑废,隨后出現(xiàn)的幾起案子蝗肪,更是在濱河造成了極大的恐慌,老刑警劉巖蠕趁,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薛闪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡俺陋,警方通過(guò)查閱死者的電腦和手機(jī)豁延,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腊状,“玉大人诱咏,你說(shuō)我怎么就攤上這事〗赏冢” “怎么了袋狞?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)映屋。 經(jīng)常有香客問(wèn)我苟鸯,道長(zhǎng),這世上最難降的妖魔是什么棚点? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任早处,我火速辦了婚禮,結(jié)果婚禮上乙濒,老公的妹妹穿的比我還像新娘陕赃。我一直安慰自己卵蛉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布么库。 她就那樣靜靜地躺著傻丝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诉儒。 梳的紋絲不亂的頭發(fā)上葡缰,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音忱反,去河邊找鬼泛释。 笑死,一個(gè)胖子當(dāng)著我的面吹牛温算,可吹牛的內(nèi)容都是我干的怜校。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼注竿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茄茁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起巩割,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤裙顽,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后宣谈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愈犹,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年闻丑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漩怎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡梆掸,死狀恐怖扬卷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酸钦,我是刑警寧澤怪得,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站卑硫,受9級(jí)特大地震影響徒恋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜欢伏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一入挣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硝拧,春花似錦径筏、人聲如沸葛假。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)聊训。三九已至,卻和暖如春恢氯,著一層夾襖步出監(jiān)牢的瞬間带斑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工勋拟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勋磕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓敢靡,卻偏偏與公主長(zhǎng)得像挂滓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啸胧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容