<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                用一道面試題考察對閉包的理解 2015年2月6日 / BY AARONJS 關于閉包的用法,幾乎是所有前端面試中必點的菜之一,也是考察javascript掌握程度的重要知識之一,下面這題,是某知名IT企業出的題型,我稍加修改,分享如下: ~~~ var name = 'global'; var obj = { name : 'obj', dose : function(){ this.name = 'dose'; return function(){ return this.name; } } } alert(obj.dose().call(this)) ~~~ 請寫出執行結果? //global 關于這樣的題型,應當怎樣去分析呢? ~~~ obj.dose().call(this) ~~~ 這個表達式有點長,看著有點眼暈,不妨進行一個等價變形。 ~~~ var xxx = obj.dose(); xxx.call(this); ~~~ 這樣就清晰多了。這樣一眼就看出是在考察call的用法和this的指向。稍有點基礎的,一眼就可以看出此處的this就是window對象。如果你看不出,就再去看看那本紅寶書3 即使知道此處的this是window還沒完。還要順路普及一下call的用途: // 1. 替換函數運行環境中的this // 2. 傳遞參數 // 3. 運行函數 通過前面的分析可以知道xxx是這樣一個函數: ~~~ function(){ return this.name; } ~~~ 由于call指定了this是window,所以return this.name 就是 window中的name,即global; 如果是面試呢,這題到此就結束了,不過舉一反三才是我的目的。因此,下面我稍改一下題目: ~~~ var name = 'global'; var obj = { name : 'obj', dose : function(){ this.name = 'dose'; return function(){ return this.name; }.bind(this) } } alert(obj.dose().call(this)) ~~~ 由于return的function中用了bind,所以相當于固定了this,外邊再call什么進來,也只是礙眼法而已。由于函數內部邦定了this,所以此處的情況要另外分析了 首先,obj對象定義了name屬性為’obj';接著在dose 方法內,又改寫了name屬性為’dose'; 根據作用域鏈的就近原則,alert訪問的肯定就是’dose’這個值了。 然而ie派認為在return中用bind不常見,兼容性也不高。那不妨再變一下: ~~~ var name = 'global'; var obj = { name : 'obj', dose : function(){ var that = this; this.name = 'dose'; return function(){ return that.name; } } } alert(obj.dose().call(this)) ~~~ 這種寫法,自然大家都比較認同了。考察還是相同的內容,只不過是邦定this的手法不一樣而已。與其說是考察閉包,不如說是考察對基礎知識的理解,因為bind,call,apply之類的方法都是平時使用頻率很高的,對它們多花點時間琢磨一下,必然是有好處的。 最后呢再分享一個面試的趣事。面試官問我,用閉包有什么好處? ## 一、**優點** **1. 延長作用域鏈。** 這一點大家是熟知的,因為閉包函數可以訪問外層函數作用域中的變量及對象,以代碼來演示一下: ~~~ function wrap () { var out = '外部變量'; return function (){ //這里可以訪問外部函數中的變量 //實際上就是創建了一個閉包函數 alert(out); } } var inner = wrap(); ~~~ //雖然wrap運行完畢了,但是inner依然可以訪問它所創建的作用域中的變量 //這就是閉包第一個用法 inner(); **2. 生成預編譯函數。** 這一點是借用jquery中的說法,實際上就是通過閉包把外層函數提供的參數保存起來,在閉包運行的時候就可以得到預先指定的參數 ~~~ var fn = []; for(var i = 0;i<3;i++){ (function(n){ fn.push(function(){ alert(n) }) })(i) } ~~~ 說化函數的curry化,可能知道的人會更多一點,和上面的例子相似, 不過它強調的是參數的積累。 ~~~ function addGenerator(num){ return function(toAdd){ return num + toAdd; }; } //創建一個新的函數 var addFive = addGenerator(5); alert(addFive(4)==9) //true ~~~ **3.更好的組織代碼,比如模塊化,異步代碼轉同步等。** ~~~ Deferred.next(function(){ alert(1) return Deferred.wait(3) }).next(function(){ alert(2) }).next(function(){ alert(3); }); ~~~ **4. 處理異步造成的變量不能即時傳遞的問題** ~~~ /** * html結構: * <ul> * <li> 0</li> * ...... * <li> 9 </li> * </ul> */ //點擊彈出對應的數字 var items = document.querySelectorAll('li'); for(var i=0;i<items.length;i++){ items[i].onclick = function(){ alert(i) } } //上面的程序結果是:每次都彈出10; //為了在用戶點擊的時候,能彈出對應的數字 // 需要構建一個閉包,將參數緩存起來 for(var i=0;i<items.length;i++){ items[i].onclick = (function(n){ return function(){ alert(n) } })(i) } // 這時點擊的時候就會彈出邦定的數字了,強烈推薦試一下 ~~~ 暫時就想到這些,其它的想到再補充。 ### 二、**缺點** 他接著又問我,那用閉包又有什么壞處? 1. 增加了內存的消耗。 2. 某些瀏覽器上因為回收機制的問題,有內存溢出風險。 3. 增加了代碼的復雜度,維護和調試不便。 我balabala說了一些,他就笑了。說你這一邊是矛,一邊是盾,到底是矛好呢還是盾好呢?當時也沒想這么多,反射性的回答說,看情況選用咯。他說這樣是不行的。 原來挖了個坑在這里等著我呢,真是太不厚道了。凡事都有兩面性嘛,只要撐握的好,自然是可以避害用利。我們都知道電是很危險,也很有用,只要掌握了它的特性,就能很好的利用,而不是受其害,所以并不是矛盾的就不可取。拿最后一個例子來說,如果不用閉包,難道就沒有辦法了嗎?顯然不是的,比如下面的代碼就不用閉包,照樣解決該問題: ~~~ function fn(n){ items[n].onclick = function(){ alert(n) } } for(var i=0;i<items.length;i++){ fn(i) } ~~~ 所以,不要認為閉包有缺點就不敢用,也不要因為閉包的優點而濫用。 是否選擇閉包,視我們的需要來定。 ## 總結 總結一點:學東西不可淺嘗則止,一定要深入原理,舉一反三,利用它的優點,規避它的缺點。
                  <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>

                              哎呀哎呀视频在线观看