<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


        《javascript高級(jí)程序設(shè)計(jì)》中閉包的概念:


          閉包,其實(shí)是一種語(yǔ)言特性,它是指的是程序設(shè)計(jì)語(yǔ)言中,允許將函數(shù)看作對(duì)象,然后能像在對(duì)象中的操作般在函數(shù)中定義實(shí)例(局部)變量,而這些變量能在函數(shù)中保存到函數(shù)的實(shí)例對(duì)象銷毀為止,其它代碼塊能通過(guò)某種方式獲取這些實(shí)例(局部)變量的值并進(jìn)行應(yīng)用擴(kuò)展。

          我們的理解:


            其實(shí)閉包就是一個(gè)函數(shù),一個(gè)外部函數(shù)通過(guò)調(diào)用函數(shù)并return返回出內(nèi)部函數(shù),這里的內(nèi)部函數(shù)就是一個(gè)閉包;此時(shí)在內(nèi)部函數(shù)中是可以訪問(wèn)到外部函數(shù)的變量的;

          


          要想理解閉包,首先我們要了解棧堆內(nèi)存和作用域鏈;首先我們來(lái)講解棧堆內(nèi)存:

             首先我們來(lái)看個(gè)demo:

              
      var a=1; var obj={"name":"咸魚"}
         上面簡(jiǎn)單的兩句代碼,其實(shí)就是在內(nèi)存中做了兩件事,效果圖如下:

        

        在js簡(jiǎn)單實(shí)現(xiàn)深淺拷貝(https://www.cnblogs.com/dengyao-blogs/p/11466598.html
      <https://www.cnblogs.com/dengyao-blogs/p/11466598.html>
      )一文中我們知道基本數(shù)據(jù)類型是存儲(chǔ)在棧內(nèi)存中的,引用數(shù)據(jù)類型是存儲(chǔ)在堆內(nèi)存中的,其實(shí)上面的兩句代碼在內(nèi)存中就是做了兩件事:1.首先在棧內(nèi)存中開(kāi)辟了一塊空間用來(lái)存放a的變量和值;2.在堆內(nèi)存中開(kāi)辟了一塊空間用來(lái)存儲(chǔ)obj的值,同時(shí)在將地址指向棧內(nèi)存中的變量名obj


        如果我們?cè)诖a下面再加上一句obj={"name":'張三"},這個(gè)時(shí)候我們之前存儲(chǔ)name為咸魚的值也就是obj原來(lái)的值會(huì)被js中的垃圾回收機(jī)制回收掉,然后obj的值重新的指向{name:"張三"}這個(gè)值;

      ?

        作用域鏈

       ? 再來(lái)看一下這個(gè)例子:
      var a = 1; function fn(){ var b = 2; function fn1(){ console.log(b);//2
      console.log(a);//1 } fn1(); } fn();
       效果圖如下:

          

      ?

      ?

      ?  1.var a=1;這個(gè)時(shí)候我們是在全局執(zhí)行環(huán)境的,瀏覽器的全局環(huán)境就是window作用域,我們的window作用域中有a和fn;

        2.當(dāng)我們往下走到fn的時(shí)候,棧內(nèi)存會(huì)開(kāi)辟一塊新的執(zhí)行環(huán)境,此時(shí)fn的執(zhí)行環(huán)境中我們有b和fn1;


        3.當(dāng)我們接著往下走到fn1的時(shí)候,這時(shí)棧內(nèi)存同樣會(huì)開(kāi)辟一塊新的執(zhí)行環(huán)境,此時(shí)fn1的執(zhí)行環(huán)境中是沒(méi)有任何變量數(shù)據(jù)的,但是我們?cè)趂n1中輸出a、b,我們都是可以讀取到的;這是因?yàn)槌绦蛟谧x取變量的時(shí)候是從內(nèi)到外的開(kāi)始讀的,是隨著fn1開(kāi)始往上一層一層的查找,是這樣的執(zhí)行順序(fn1
      = > fn = > window),如果找到window中還沒(méi)有讀取到變量,這時(shí)程序才會(huì)報(bào)錯(cuò);


        當(dāng)然在執(zhí)行的過(guò)程中,垃圾回收機(jī)制如果檢測(cè)到程序執(zhí)行完了是會(huì)進(jìn)行垃圾回收的,避免造成內(nèi)存泄露等問(wèn)題;就是說(shuō)我們的fn1里面執(zhí)行完之后fn1的作用域就會(huì)被銷毀,接著程序執(zhí)行fn,fn執(zhí)行完之后fn就會(huì)被銷毀;往上執(zhí)行到全局的時(shí)候,整個(gè)程序就沒(méi)有了fn的作用域和fn1的作用域,只剩下瀏覽器的全局作用域window,這個(gè)時(shí)候window里只剩a和fn;

      ?

       ? 了解了上面的作用域鏈和棧內(nèi)存和堆內(nèi)存的知識(shí)之后,我們來(lái)開(kāi)始講解js閉包:

        
      function outer() { var a = '123' return function add(){
          //在這里因?yàn)樽饔糜虻年P(guān)系,add是能訪問(wèn)到outer的所有變量的,但是outer是訪問(wèn)不到add的變量;
          //所以思路一轉(zhuǎn),把a(bǔ)dd的值作為結(jié)果return出來(lái)變通實(shí)現(xiàn)outer外部函數(shù)訪問(wèn)到了內(nèi)部函數(shù)變量
      // add就是一個(gè)閉包函數(shù),因?yàn)樗軌蛟L問(wèn)到outer函數(shù)的作用域,add中沒(méi)有找到變量a,則會(huì)繼續(xù)往上層作用域找 console.log(a); } }
      var inner = outer() // 獲得add閉包函數(shù) inner() //"123"
      ?

          
      首先我們可以看到,在全局作用域下我們是有一個(gè)outer函數(shù)的,outer作用域里面有a和add,add作用域里面執(zhí)行控制臺(tái)輸出a的變量,此時(shí)這里的add函數(shù)就形成了一個(gè)閉包,因?yàn)閍dd函數(shù)里面需要訪問(wèn)到outer作用域下的a變量,而他們不處在同一個(gè)作用域中,所以兩者相互牽引,需要輸出a,上面outer中的變量a就必須得在,輸出a的時(shí)候,垃圾回收機(jī)制會(huì)認(rèn)為上面的程序還沒(méi)有執(zhí)行完成,所以不會(huì)清理a的內(nèi)存空間;所以這就會(huì)帶來(lái)一個(gè)問(wèn)題:如果我們多次的使用閉包,則會(huì)給我們的程序帶來(lái)內(nèi)存占用過(guò)多,導(dǎo)致性能問(wèn)題;


          函數(shù)內(nèi)部能訪問(wèn)全局變量是javascript語(yǔ)言的特殊之處,但是如果我們想達(dá)到函數(shù)外部能訪問(wèn)內(nèi)部變量的時(shí)候,我們就可以使用閉包,這就是閉包給我們帶來(lái)的便利;

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

            優(yōu)點(diǎn):

              1.可以讀取函數(shù)內(nèi)部的變量
              2.可以避免全局污染

            缺點(diǎn):

              1.閉包會(huì)導(dǎo)致變量不會(huì)被垃圾回收機(jī)制所清除,會(huì)大量消耗內(nèi)存;

              2.不恰當(dāng)?shù)氖褂瞄]包可能會(huì)造成內(nèi)存泄漏的問(wèn)題;

      總結(jié):

        1.作用域鏈查找變量的方式是一層一層的往上查找,直到找到為止,如果找到window全局作用域還未找到,就報(bào)undefined;

        2.嵌套函數(shù)中,因?yàn)椴辉谕蛔饔糜颍G闆r下內(nèi)部函數(shù)是訪問(wèn)不到外部函數(shù)的,但是通過(guò)閉包可以實(shí)現(xiàn);

        3.盡可能少的使用閉包,因?yàn)闀?huì)造成內(nèi)存消耗大以及有可能造成內(nèi)存泄露(如果不需要的時(shí)候,不要隨便使用);

        

      ?

        

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          欧美大波大乳巨大乳 | 欧美高清中文字幕 | 国产精品久久欠久久久久久九秃大 | 黄色片黄色片黄色片黄色片黄色片黄色片 | 人人草人人搞 | 婷婷久久五月天 | 百合嗯啊+摸+湿+内裤+gl | 熟女少妇内射日韩亚洲 | 国产精品久久久久劲爆 | 国产成年人在线观看 |