<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之旅 廣告
                閉包是javascript的一個難點,也是一個重點,很多高級應用都需要用到閉包。在學習閉包的過程中看了不少書和大牛的博客,下面來說說我對閉包的理解和看法。 ### 函數 要說閉包就不得不先說一下函數,這個javascript的中流砥柱。 眾所周知在ES6之前js都沒有class這個關鍵字,一切的面向對象都是通過function模擬的。 一個簡單到不能再簡單的例子:函數內部可以訪問外部的變量(全局變量)。 ~~~ var n=100; function f1() { console.log(n); } f1();//100 ~~~ <br> 而外部卻不能訪問函數內的局部變量。 ~~~ function f1() { var n=100; } console.log(n);//n is not defined ~~~ <br/> 那么問題來了,如果我想訪問函數內的局部變量怎么辦?一種解決辦法就是使用閉包。 什么是閉包?我個人認為函數中的函數就是閉包,有點像java的內部類,既然函數可以訪問外部變量,那么函數中的函數也可以訪問外層函數的變量,這個內層函數就是閉包。 ~~~ function f1() { var n=100; function f2() { console.log(n); } f2(); } f1();//100 ~~~ 上述寫法比較麻煩,因此可以把f2作為一個返回值返回給f1。 ~~~ function f1() { var n=100; function f2() { console.log(n); } return f2; } f1()();//100 //相當于var f=f1();f(); ~~~ <br> 下面來看一個問題:這里有5個li,名字是0到4,我希望我點擊0的時候在控制臺輸出0,點擊1的時候在控制臺輸出1,以此類推。 ~~~ var lis=document.getElementsByTagName("li"); for(var i=0;i<lis.length;i++) { lis[i].onclick=function() { console.log(i); } } ~~~ 奇怪的事情發生了,無論我點擊哪一個在控制臺輸出的都是5。 這是為什么呢? 仔細觀察,我為每個li創建了一個匿名函數,匿名函數形成了閉包,它們都在引用外部的i,當i改變時,自然所有匿名函數里面的i都改變了。用幾張圖來說明。 ![](https://box.kancloud.cn/2016-05-19_573d3ecda20ee.JPG) ![](https://box.kancloud.cn/2016-05-19_573d3ecdb94e8.JPG) ![](https://box.kancloud.cn/2016-05-19_573d3ecdce960.JPG) 當i增加到5的時候不再滿足循環條件,由于五個匿名函數都是引用同一個i,所以它們打印出來的都是5。 既然它們是引用同一個i,那么只需為每一個i創建一個備份 ~~~ var lis=document.getElementsByTagName("li"); for(var i=0;i<lis.length;i++) { lis[i].onclick=function(num) { return function() { console.log(num); } }(i) } ~~~ 這里在匿名函數接收一個參數并且立即執行,匿名函數內部又創建了一個函數負責把這個參數返回給匿名函數,由于是按值傳遞的,所以相當于給i做了一個備份。就算i一直在改變,而每個匿名函數的num是固定的。 <br> ### 閉包中的this 在閉包中使用this會出現一些問題,在全局函數中this指向的是window,當函數以方法被調用時,this就指向這個對象。但是,匿名函數的執行環境具有全局性,this一般指向window。參考紅寶石書中的一個經典的問題: ~~~ var name="The Window"; var object={ name:"My Object", getNameFunc:function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());//"The Window" ~~~ 內部函數在搜索this的時候只會搜到其活動對象為止,由于匿名函數的執行環境具有全局性,因此當前的活動對象就是window。 <br> 可以通過改變當前的活動對象來改變this的指向 ~~~ 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對象賦值給了一個that變量,因此當前的活動對象就從window變成了object。 <br> ### 閉包引發的問題 閉包雖好,但是也引發了一系列問題,尤其是內存泄漏。js的垃圾回收機制是引用計數的,當一個變量不再使用的時候(引用計數為0)垃圾回收機制就會把它清理掉。而閉包的存在會導致引用數至少為1。 ~~~ function f() { var myDiv=document.getElementById("Div1"); myDiv.onclick=function() { console.log(myDiv.id); }; } ~~~ 上述代碼中,函數f需要等myDiv清除后才能被清除,而myDiv由于匿名函數的存在,它的引用數至少為1,因此它所占用的內存永遠不會被回收。 <br> 解決辦法: ~~~ function f() { var myDiv=document.getElementById("Div1"); var id=myDiv.id myDiv.onclick=function() { console.log(id); }; myDiv=null; } ~~~ 把myDiv.id保存在一個變量中,并且在閉包中引用這個變量,這樣就與myDiv沒有關系了。但是閉包會引用包含函數的整個活動對象,因此必須把myDiv設為null來解除對它的引用,確保垃圾回收機制能夠把資源回收。 <br> 使用閉包應該注意的問題:閉包雖然好,但是在實際應用中盡量減少 閉包的使用,并且為了防止內存泄漏,要時刻記得在閉包完后清除它的局部變量。
                  <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>

                              哎呀哎呀视频在线观看