<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## 7.2 閉包 * 一個函數返回值是另一個函數; * 返回的函數調用了父函數內部的其他變量; * 返回的函數在外部被執行。 于是,產生了**閉包**。 ### 7.2.1.變量的作用域 變量的作用域有兩種:**全局變量和局部變量。** Javascript語言的特殊之處,就在于**函數內部可以直接讀取全局變量。** ~~~   var n=999;   function f1(){     alert(n);   }   f1(); // 999 ~~~ 另一方面,在函數外部自然無法讀取函數內的局部變量。 ~~~   function f1(){     var n=999;   }   alert(n); // error ~~~ 出于種種原因,我們有時候需要得到函數內的局部變量。于是采用變通的手段:**在函數的內部,再定義一個函數。** ~~~   function f1(){     var n=999;     function f2(){       alert(n); // 999     }   } ~~~ 在上面的代碼中,函數f2就被包括在函數f1內部,這時f1內部的所有局部變量,對f2都是可見的。但是反過來就不行,f2內部的局部變量,對f1就是不可見的。這就是Javascript語言特有的"作用域鏈"結構(chain scope),子對象會一級一級地向上尋找所有父對象的變量。所以,父對象的所有變量,對子對象都是可見的,反之則不成立。 既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,我們就可以在f1外部讀取它的內部變量了。 ~~~ function f1() { var n = 999; function f2() { console.log(n); } return f2; } var result = f1(); result(); // 999 ~~~ ### 7.2.2 閉包的作用 本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。 閉包的最大用處有兩個:一個是可以**讀取函數內部的變量**,另一個就是**讓函數內部變量始終保持在內存中**,即閉包可以使得它誕生環境一直存在。 請看下面的例子,閉包使得內部變量記住上一次調用時的運算結果。 ~~~ function createIncrementor(start) { return function () { return start++; }; } var inc = createIncrementor(5); inc() // 5 inc() // 6 inc() // 7 ~~~ 上面代碼中,start是函數createIncrementor的內部變量。通過閉包,start的狀態被保留了,每一次調用都是在上一次調用的基礎上進行計算。從中可以看到,閉包inc使得函數createIncrementor的內部環境,一直存在。所以,**閉包可以看作是函數內部作用域的一個接口**。 為什么會這樣呢?原因就在于inc始終在內存中,而`inc的存在依賴于createIncrementor`,因此也始終在內存中,不會在調用結束后,被垃圾回收機制回收。 閉包的另一個用處,是**封裝對象的私有屬性和私有方法。** ~~~ function Person(name) { var _age; function setAge(n) { _age = n; } function getAge() { return _age; } return { name: name, getAge: getAge, setAge: setAge }; } var p1 = Person('張三'); p1.setAge(25); p1.getAge() // 25 ~~~ 上面代碼中,函數Person的內部變量`_age`,通過閉包`getAge和setAge`,變成了返回對象p1的**私有變量**。 注意:外層函數每次運行,都會生成一個新的閉包,而這個閉包又會保留外層函數的內部變量,所以**內存消耗很大**。因此不能濫用閉包,否則會造成網頁的性能問題。 ### 7.2.3 關于this對象 **this對象**是在運行時基于函數的執行環境綁定的:在全局函數中,this等于window,而當函數被作為某個對象的方法調用是,this等于那個對象。 但是,**匿名函數**的執行環境具有**全局性**,因此其this對象通常指向window。(通過call()或apply()改變執行環境情況除外) ~~~ var name = "The Window";   var object = {     name : "My Object",     getNameFunc : function(){       return function(){         return this.name;       };     }   };   alert(object.getNameFunc()()); //“The Window” ~~~ 為什么匿名函數沒有取得其包含作用域(或外部作用域)的this對象? 每個函數在被調用時都會自動取得兩個特殊變量:this和arguments。內部函數在搜索這兩個變量時,只會搜索到其活動對象為止,因此不可能直接訪問外部函數中的這兩個變量。 ~~~ var name = "The Window";   var object = {     name : "My Object",     getNameFunc : function(){       var that = this; ←看這       return function(){         return that.name;       };     }   };   alert(object.getNameFunc()()); //"My Object" ~~~ 把外部作用域中的this對象保存在一個閉包能夠訪問到的變量里,就可以讓閉包訪問該對象了。 ### 7.2.4 模仿塊級作用域 匿名函數可以用來模仿塊級作用域,避免重復聲明同一變量; 用作私有作用域的匿名函數語法如下: ~~~ (function(){ //塊級作用域(私有作用域); })(); ~~~ 將函數聲明包含在一對括號內,會將函數聲明轉換成函數表達式,函數表達式后面緊跟的`()`會立即調用這個函數。 ~~~ function outputNumbers(count) { for (var i = 0; i < count; i++) { alert(i); //0,1,2,3,4 } alert(i); //5 } ~~~ 改寫后 ~~~ function outputNumbers(count) { (function () { for (var i = 0; i < count; i++) { alert(i); //0,1,2,3,4 } })(); alert(i); //error } ~~~ 在匿名函數中定義的任何變量,都會在執行結束時被銷毀,因此,變量i只能在循環中使用。 在私有作用域中能夠訪問變量count,是因為這個匿名函數是一個閉包,能夠訪問包含作用域中的所有變量。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看