<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閉包,是JS開發工程師必須深入了解的知識。3月份自己曾撰寫博客《[JavaScript閉包](http://blog.csdn.net/ligang2585116/article/details/44702115)》,博客中只是簡單闡述了閉包的工作過程和列舉了幾個示例,并沒有去刨根問底,將其弄明白! 現在隨著對JavaScript更深入的了解,也剛讀完《**你不知道的JavaScript(上卷)**》這本書,所以乘機整理下,從底層和原理上去刨一下。 JavaScript并不具有動態作用域,它只有詞法作用域。詞法作用域是在寫代碼或者說定義時確定的,而動態作用域是在運行時確定的。了解閉包前,首先我們得知道什么是詞法作用域(作用域是由書寫代碼時函數聲明的位置來決定的)。 ### 一、何為閉包 #### 示例1: ~~~ function foo(){ var a = 2; function bar(){ console.log(a); } return bar; } var baz = foo(); bzz(); //2 ~~~ 在foo()執行后,通常認為垃圾回收機制會將foo()的整個內部作用域都被銷毀;而閉包可以阻止這樣事情發生,讓其內部作用域依然存在。因為bar()處于foo()內部,它擁有涵蓋foo()作用域的閉包,使得該作用域能夠一直存活,以供bar()在之后任何時間進行引用。 bar()依然持有對該作用域的引用,而這個引用就叫作**閉包**。 簡言之:當函數可以記住并訪問所在的詞法作用域,即使函數是在當前詞法作用域之外執行,這時就產生了閉包。 #### 示例2: 無論使用何種方式對函數類型的值進行傳遞,當函數在別處被調用時都可以觀察到閉包。 ~~~ function foo(){ var a = 2; function baz(){ console.log(a); } bar(baz); } function bar(fn){ fn(); // 這就是閉包 } ~~~ #### 示例3: 將一個內部函數(timer)傳遞給setTimeout。timer具有涵蓋wait()作用域的閉包,保有對變量message的引用。 wait()執行1000毫秒后,它的作用域并不會消失,timer依然保有wait()作用域的閉包。 ~~~ function wait(message){ setTimeout( function timer(){ console.log(message); },1000); } wait("Hello,ligang"); ~~~ #### 示例4: 下述activator()具有涵蓋setupBot()作用域的閉包! ~~~ function setupBot(name, selector){ $(selector).click(function activator(){ console.log("Activating: "+ name); }); } setupBot("Closure Bot 1", "#bot_1"); setupBot("Closure Bot 2", "#bot_2"); ~~~ ### 二、循環和閉包 ~~~ for(var i=1; i<=5; i++){ setTimeout(function timer(){ console.log(i); }, i*1000); } // 期望:每秒一次的頻率輸出1~5 // 結果:每秒一次的頻率輸出五次6 ~~~ 先解釋一下:“i*1000”,5個定時分別在1s、2s、3s、4s、5s后執行,并不是1s、3s、6s、10s、15s。也就是頻率為1s,不是每次間隔增加1s。如果去掉i寫成“1000”,會在for執行完1s后直接輸出五次6。 回調函數在循環結束后才被執行,因此輸出的是循環終止條件是i值。事實上,當定時器運行時即使每個迭代中執行的是setTimeout(..., 0),所有的回調函數依然是在循環結束后才被執行。 根據作用域的工作原理,盡管五個函數是在各個迭代中分別定義的,但是它們都被封閉在一個共享的全局作用域中,因此實際上只有一個i。 ### 解決方案1: ~~~ for(var i=0; i<=5; i++){ (function(j){ setTimeout(function timer(){ console.log(j); }, j*1000 ); })(i); } // 結果:每秒一次的頻率輸出1~5 ~~~ 每個迭代都生成一個新的作用域,使得延遲函數的回調可以將新的作用封閉在每個迭代內部,每個迭代中都會含有一個具有正確值的變量供我們訪問。 ### 解決方案2(ES6): ~~~ for(var i=0; i<=5; i++){ let j = i; setTimeout(function timer(){ console.log(j); }, j*1000 ); } // 結果:每秒一次的頻率輸出1~5 ~~~ ~~~ for(let i=0; i<=5; i++){ setTimeout(function timer(){ console.log(i); }, i*1000 ); } // 結果:每秒一次的頻率輸出五次6 ~~~ ### 三、模塊 模塊需要具備兩個必要條件: (1)必須有外部的封閉函數,該函數必須至少被調用一次(每次調用都會創建一個新的模塊實例)。 (2)封閉函數必須返回至少一個內部函數,這樣內部函數才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態。 #### 典型的模塊化: ~~~ function CoolMoudle(){ var something = "cool"; var doSomething = function(){ console.log(something); } return{ doSomething: doSomething }; } var foo = CoolMoudle(); //如果不執行外部函數CoolMoudle(),內部作用域和閉包都無法創建 foo.doSomething(); //cool ~~~ #### 單例模式: ~~~ var foo = (function CoolModule(id){ function change(){ // 修改公共API publicAPI.identify = identify2; } function identify1(){ console.log(id); } function identify2(){ console.log(id.toUpperCase()); } var publicAPI = { change: change, identify: identify1 }; return publicAPI; })("foo module"); foo.identify(); //foo module foo.change(); foo.identify(); //FOO MODULE ~~~
                  <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>

                              哎呀哎呀视频在线观看