閉包,關于閉包用途

1. JS中變量的作用域

在理解閉包之前,我們得弄清楚JS中變量的作用域原理,它分為全局作用域和局部作用域,它有一個特點就是局部可以獲取全局的聲明變量,而全局卻不能得到局部聲明的變量,我們先來看一個小例子:

                                     var num = 1902;

                                     function methods() {

                                       var qty = 25;

                                       console.log(num);

                                     }

                                     methods();  // 1902
  
                                     console.log(qty);  // 報錯,找不到 qty 變量;

當然在局部聲明變量的時候一定要用var或者let,不然會在全局生成一個變量,容易照成全局污染,上面代碼如果qty沒有var聲明:

                                    var num = 1902;

                                    function methods() {

                                        qty = 25;

                                        console.log(num);

                                     }

                                     methods();  // 1902;

                                     console.log(qty);  // 25;

2.什么是閉包

那么現(xiàn)在問題來了,如果我們非要從外部來讀取局部變量中的聲明變量呢,尋常方式不行,我們可以變通一下,就是在函數(shù)內(nèi)部再嵌套一個函數(shù),然后返回這個嵌套函數(shù):

                                           function methods() {

                                                 var qty = 25;

                                                 return function num() {

                                                 console.log(qty);

                                                }
  
                                             }

                                            var num1 = methods();

                                            num1()  // 25

這樣,控制臺就會打印出 qty 變量的值了,其實在上面的代碼中,被返回的函數(shù) num()就產(chǎn)生了閉包,由于在js中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,所以可以把閉包理解成定義在一個函數(shù)內(nèi)部的函數(shù),簡單的說,JavaScript允許使用內(nèi)部函數(shù):即函數(shù)定義和函數(shù)表達式位于另一個函數(shù)的函數(shù)體內(nèi)而且,這些內(nèi)部函數(shù)可以訪問它們所在的外部函數(shù)中聲明的所有局部變量、參數(shù)和聲明的其他內(nèi)部函數(shù)。當其中一個這樣的內(nèi)部函數(shù)在包含它們的外部函數(shù)之外被調(diào)用時,就會形成閉包。

3.閉包的用途

我們接著探討閉包的表達形式以及用途。
(1)匿名自執(zhí)行函數(shù)

                                         (function () {
                                            var methods = function () {
                                                console.log('執(zhí)行完函數(shù)后銷毀')
                                            };
                                            methods();
                                        })();

上面代碼也是閉包的應用,運用于函數(shù)只會執(zhí)行一次的場景,執(zhí)行完便會被釋放。
(2)給對象設置私有變量

                                      var result = function () {
                                             var count = 1;
                                             return function () {
                                                  count++;
                                                  console.log(count)
                                              }
                                        }()
                                          result(); // 2
                                          result(); // 3
                                          result(); // 4
                                          result(); // 5

上面代碼可以保存自己的私有變量,防止代碼之間的沖突。
(3)異步執(zhí)行函數(shù)
下面先看一個小例子:

                                      for (var i = 0; i < 5; i++) {
                                              console.log(i);  //0,1,2,3,4
                                      }
                                      for (var i = 0; i < 5; i++) {
                                             setTimeout(() => {
                                                     console.log(i); //5,5,5,5,5
                                            }, 0)
                                      }

為什么會出現(xiàn)上述差異呢,原因在于setTimeout是異步加載,所以為先循環(huán)結(jié)束后輸出最后結(jié)果,如果我們就是想實現(xiàn)輸出0,1,2,3,4呢。那就要用到閉包了:

                                          for (var i = 0; i < 5; i++) {
                                                (function (i) {
                                                      setTimeout(() => {
                                                            console.log(i); //0,1,2,3,4
                                                      }, 0);
                                                })(i);
                                            }

上面就是異步調(diào)用閉包,它可以讓變量值始終保存在內(nèi)存中,即使外部的執(zhí)行環(huán)境已經(jīng)結(jié)束了。

4.閉包的優(yōu)缺點

(1)由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。

(2)閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內(nèi)部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • ??函數(shù)表達式是 JavaScript 中的一個既強大有容易令人困惑的特性。定義函數(shù)的的方式有兩種: 函數(shù)聲明; ...
    霜天曉閱讀 892評論 0 1
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,144評論 2 9
  • 閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高級應用都要依靠閉包實現(xiàn)。 一、變量...
    風蕭蕭易水寒_1196閱讀 310評論 0 0
  • 1 概述 1.1函數(shù)的聲明 JavaScript 有三種聲明函數(shù)的方法。 (1)function 命令 funct...
    徵羽kid閱讀 455評論 0 1
  • 函數(shù)是一段可以反復調(diào)用的代碼塊。函數(shù)還能接受輸入的參數(shù),不同的參數(shù)會返回不同的值。 概述 函數(shù)的聲明 JavaSc...
    許先生__閱讀 498評論 0 1

友情鏈接更多精彩內(nèi)容