丸子學(xué)JS(學(xué)習(xí)1小時 - 閉包的應(yīng)用)

何為閉包

如果一個函數(shù)訪問了此函數(shù)的父級及父級以上的作用域變量咕别,那這個函數(shù)就是一個閉包

本質(zhì)上, JS中的每個函數(shù)都是一個閉包烫罩,因為每個函數(shù)都可以訪問全局變量

閉包的執(zhí)行過程

function a() {
    var i = '初始值';
    i = i + "—_執(zhí)行a"
    // 此處的函數(shù)b訪問了父級函數(shù)a中的局部變量i,成為了一個閉包
    function b() {
        i = i + "_執(zhí)行b"
        console.log(i)
    }
    return b;
}
var c = a(); // 此時 i 的值為 :初始值—_執(zhí)行a
c()          // 此時 i 的值為 :初始值—_執(zhí)行a_執(zhí)行b
c()          // 此時 i 的值為 :初始值—_執(zhí)行a_執(zhí)行b_執(zhí)行b
  1. 將函數(shù)a賦值給全局變量c時赏迟,a會執(zhí)行一次,局部變量 i 的值變?yōu)槌跏贾怠?em>執(zhí)行a妥凳,最終返回函數(shù)b竟贯,此時全局變量c的值為閉包函數(shù)b的引用。
    此時函數(shù)a雖然已執(zhí)行完逝钥,但因為內(nèi)部包含閉包函數(shù)b澄耍,所以函數(shù) a 的執(zhí)行期上下文會繼續(xù)保留在內(nèi)存中,不會被銷毀晌缘,所以局部變量 i 仍是初始值—執(zhí)行a

執(zhí)行期上下文:當(dāng)函數(shù)執(zhí)行時齐莲,會創(chuàng)建一個執(zhí)行期上下文的內(nèi)部對象。每調(diào)用一次函數(shù)磷箕,就會創(chuàng)建一個新的上下文對象选酗,他們之間是相互獨(dú)立的。當(dāng)函數(shù)執(zhí)行完畢岳枷,它所產(chǎn)生的執(zhí)行期上下文會被銷毀

  1. 第一次執(zhí)行 c() 時芒填,閉包函數(shù)b第一次執(zhí)行俺榆,局部變量 i 的值變?yōu)槌跏贾怠?em>執(zhí)行a執(zhí)行b
  2. 第二次執(zhí)行 c() 時,閉包函數(shù)b第二次執(zhí)行落塑,局部變量 i 的值變?yōu)槌跏贾怠?em>執(zhí)行a執(zhí)行b_執(zhí)行b

圖解閉包

var a = "global variable";
var F = function () {
  var b = "local variable";
  var N = function () {
    var c = "inner local";
    return b;
  };
 return N;
};
var d = F()
d()

● 全局作用域 G 中有:
○ —— 函數(shù) F
○ —— 全局變量 a
○ —— 全局變量 d (存有對閉包函數(shù) N 的引用)
● 函數(shù) F 中有:
○ —— 返回閉包函數(shù)N
○ —— 函數(shù) F 作用域中的局部變量 b
○ —— 閉包函數(shù) N
● 閉包函數(shù) N 中有:
○ —— 返回局部變量b
○ —— 函數(shù) N 作用域中的局部變量 c

閉包的特點(diǎn)

  1. 被閉包函數(shù)訪問的父級及以上的函數(shù)的局部變量會一直存在于內(nèi)存中蛤克, 不會被JS的垃圾回收機(jī)制回收

2.閉包函數(shù)實現(xiàn)了對其他函數(shù)內(nèi)部變量的訪問。(函數(shù)內(nèi)部的變量對外是無法訪問的闷祥,閉包通過這種變通的方法娱颊,實現(xiàn)了訪問。)

閉包的用途

1.訪問函數(shù)內(nèi)部的變量
2.讓變量始終保持在內(nèi)存中

閉包的應(yīng)用場景

模擬面向?qū)ο蟮拇a風(fēng)格

模擬兩人對話

function person(name) {
    function say(content) {
        console.log(name + ':' + content)
    }
    return say
}

a = person("張三")
b = person("李四")
a("在干啥凯砍?")
b("沒干啥箱硕。")
a("出去玩嗎?")
b("去哪拔蝰谩剧罩?")

================打印start================
張三:在干啥?
李四:沒干啥座泳。
張三:出去玩嗎惠昔?
李四:去哪啊挑势?    
================打印end================
使setTimeout支持傳參

通過閉包實現(xiàn)setTimeout第一個函數(shù)傳參(默認(rèn)不支持傳參)

function func(param){
    return function(){
        alert(param)
    }
}
var f1 = func(1);
setTimeout(f1,1000);
封裝私有變量
//用閉包定義能訪問私有函數(shù)和私有變量的公有函數(shù)舰罚。
var counter = (function () {
    var privateCounter = 0; //私有變量
    function change(val) {
        privateCounter += val;
    }
    return {
        increment: function () {
            change(1);
        },
        decrement: function () {
            change(-1);
        },
        value: function () {
            return privateCounter;
        }
    };
})();

console.log(counter.value());//0
counter.increment();
console.log(counter.value());//1
counter.increment();
console.log(counter.value());//2
模擬塊作用域
var elements = document.getElementsByTagName('li');
var length = elements.length;
for (var i = 0; i < length; i++) {
    elements[i].onclick = function (num) {
        return function () {
            alert(num);
        };
    }(i);
}
實現(xiàn)迭代器
function setup(x) {
  var i = 0;
  return function(){
    return x[i++];
  };
}
var next = setup(['a', 'b', 'c']);

================打印start===============
> next();
"a"
> next();
"b"
> next();
"c"
================打印end===============

閉包的優(yōu)點(diǎn)

  1. 可以減少全局變量的定義,避免全局變量的污染
  2. 能夠讀取函數(shù)內(nèi)部的變量
  3. 在內(nèi)存中維護(hù)一個變量薛耻,可以用做緩存

閉包的缺點(diǎn)

  1. 造成內(nèi)存泄露
  2. 閉包可能在父函數(shù)外部营罢,改變父函數(shù)內(nèi)部變量的值
  3. 造成性能損失

閉包范例

返回匿名閉包
function funA(){
  var a = 10;  // funA的活動對象之中;
  return function(){   //匿名函數(shù)的活動對象;
        alert(a);
  }
}
var b = funA();
b();  //10
各自獨(dú)立的閉包
function outerFn(){
  var i = 0; 
  function innerFn(){
      i++;
      console.log(i);
  }
  return innerFn;
}
var inner = outerFn();  //每次外部函數(shù)執(zhí)行的時候,都會開辟一塊內(nèi)存空間,外部函數(shù)的地址不同,都會重新創(chuàng)建一個新的地址
inner();
inner();
inner();
var inner2 = outerFn();
inner2();
inner2();
inner2();   //1 2 3 1 2 3
訪問全局變量的閉包
var i = 0;
function outerFn(){
  function innnerFn(){
       i++;
       console.log(i);
  }
  return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2();     //1 2 3 4
閉包的鏈?zhǔn)秸{(diào)用
var add = function (x) {
    var sum = 1;
    var tmp = function (x) {
        console.log('執(zhí)行tmp')
        sum = sum + x;
        return tmp;
    }
    tmp.toString = function () {
        return sum;
    }
    return tmp;
}
console.log(add(1)(2)(3).toString())

===============打印start================
執(zhí)行tmp
執(zhí)行tmp
6
===============打印end================
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饼齿,一起剝皮案震驚了整個濱河市饲漾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缕溉,老刑警劉巖考传,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異证鸥,居然都是意外死亡僚楞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門枉层,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泉褐,“玉大人,你說我怎么就攤上這事鸟蜡∧ぴ撸” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵揉忘,是天一觀的道長跳座。 經(jīng)常有香客問我端铛,道長,這世上最難降的妖魔是什么疲眷? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任禾蚕,我火速辦了婚禮,結(jié)果婚禮上狂丝,老公的妹妹穿的比我還像新娘换淆。我一直安慰自己,他們只是感情好美侦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著魂奥,像睡著了一般菠剩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耻煤,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天具壮,我揣著相機(jī)與錄音,去河邊找鬼哈蝇。 笑死棺妓,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炮赦。 我是一名探鬼主播怜跑,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吠勘!你這毒婦竟也來了性芬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤剧防,失蹤者是張志新(化名)和其女友劉穎植锉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峭拘,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俊庇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸡挠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辉饱。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拣展,靈堂內(nèi)的尸體忽然破棺而出鞋囊,到底是詐尸還是另有隱情,我是刑警寧澤瞎惫,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布溜腐,位于F島的核電站译株,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挺益。R本人自食惡果不足惜歉糜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望望众。 院中可真熱鬧匪补,春花似錦、人聲如沸烂翰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甘耿。三九已至踊兜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佳恬,已是汗流浹背捏境。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毁葱,地道東北人垫言。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像倾剿,于是被迫代替她去往敵國和親筷频。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

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