亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

jQuery鏈式操作

系統(tǒng) 2787 0

兩個問題

1.jQuery的鏈式操作是如何實現(xiàn)的?

2.為什么要用鏈式操作?

大家認為這兩個問題哪個好回答一點呢?

?

鏈式操作

原理相信百度一下一大把,實際上鏈式操作僅僅是通過對象上的方法最后

return this

把對象再返回回來,對象當然可以繼續(xù)調用方法啦,所以就可以鏈式操作了。那么,簡單實現(xiàn)一個:

      
        //
      
      
        定義一個JS類
      
      
        function
      
      
         Demo() {

}

      
      
        //
      
      
        擴展它的prototype
      
      
Demo.prototype =
      
        {
    setName:
      
      
        function
      
      
         (name) {
        
      
      
        this
      
      .name = 
      
        name;
        
      
      
        return
      
      
        this
      
      
        ;
    },
    getName:
      
      
        function
      
      
         () {
        
      
      
        return
      
      
        this
      
      
        .name;
    },
    setAge:
      
      
        function
      
      
         (age) {
        
      
      
        this
      
      .age = 
      
        age;
        
      
      
        return
      
      
        this
      
      
        ;
    }
};


      
      
        //
      
      
        //工廠函數(shù)
      
      
        function
      
      
         D() {
    
      
      
        return
      
      
        new
      
      
         Demo();
}

      
      
        //
      
      
        去實現(xiàn)可鏈式的調用
      
      
D().setName("CJ").setAge(18).setName();
    

?

但……為什么要用呢?

一般的解釋:

節(jié)省代碼量,代碼看起來更優(yōu)雅。

例如如果沒有鏈式,那么你可能需要這樣寫代碼:

      document.getElementById("ele"
      
        ).dosomething();
document.getElementById(
      
      "ele").dootherthing();
    

這個代碼中調用了兩次document.getElementById來獲取DOM樹的元素,這樣消耗比較大,而且要寫兩行,而鏈式只要寫一行,節(jié)省了代碼……

但我們也可以用緩存元素啊。比如:

      
        var
      
       ele = document.getElementById("ele"
      
        );
ele.dosomething();
ele.dootherthing();
      
    

而且兩行并沒有比一行多多少代碼,甚至相應的封裝反而使得代碼更多了。

最糟糕的是所有對象的方法返回的都是對象本身,也就是說沒有返回值,這不一定在任何環(huán)境下都適合。

舉個例子,我們想弄一個超大整數(shù)BigInteger(意思是如果用Javascript的Number保存可能會溢出的整數(shù)),順便擴展他的運算方法,會適合用鏈式操作么?

?例如運算3 1415926535 * 4 -? 271828182,如果設計成鏈式風格的方法可能會是這樣的:

      
        var
      
       result = (
      
        new
      
       BigInteger("31415926535")).multiply(
      
        new
      
       BigInteger("4")).subtract(
      
        new
      
       BigInteger("271828182"
      
        )).val();
console.log(
      
      "result == " + result);
    

這看起來似乎也很優(yōu)雅,但是如果我們想要中間的結果怎么辦呢?或許會寫成這樣:

      
        var
      
       bigInteger = 
      
        new
      
       BigInteger("31415926535"
      
        );

      
      
        var
      
       result1 = bigInteger.multiply(
      
        new
      
       BigInteger("4"
      
        )).val();

      
      
        var
      
       result2 = bigInteger.subtract(
      
        new
      
       BigInteger("271828182"
      
        )).val();
console.log(
      
      "result1 == " + result1 + ", result2 == " + result2);
    

這似乎一點也不優(yōu)雅了,和不用鏈式操作沒啥不同嘛!

那么如果要求是原來的BigInteger不能改變呢?好吧,鏈式操作似乎不能滿足這個需求了。

jQuery專注于DOM對象操作,而DOM的操作會在頁面上體現(xiàn),不需要在Javascript中通過返回值來表示,但計算操作卻不一樣,我們很可能需要通過Javascript返回中間過程值另作他用。

在設計的時候,我們需要考慮鏈式帶來的好處和壞處,因為別人用了鏈式,所以就用鏈式,可能并不是一個很好的方案。

那么到底為什么要用鏈式操作呢?


為了更好的異步體驗

Javascript是無阻塞語言,所以他不是沒阻塞,而是不能阻塞,所以他需要通過事件來驅動,異步來完成一些本需要阻塞進程的操作。

但是異步編程是一種令人瘋狂的東西……運行時候是分離的倒不要緊,但是編寫代碼時候也是分離的就……

常見的異步編程模型有哪些呢?

  • 回調函數(shù)?

所謂的回調函數(shù),意指先在系統(tǒng)的某個地方對函數(shù)進行注冊,讓系統(tǒng)知道這個函數(shù)的存在,然后在以后,當某個事件發(fā)生時,再調用這個函數(shù)對事件進行響應。

      
        function
      
      
         f(num, callback){  
    
      
      
        if
      
      (num<0
      
        )  {   
        alert(
      
      "調用低層函數(shù)處理!"
      
        );  
        alert(
      
      "分數(shù)不能為負,輸入錯誤!"
      
        );   
    }
      
      
        else
      
      
        if
      
      (num==0
      
        ){  
        alert(
      
      "調用低層函數(shù)處理!"
      
        );  
        alert(
      
      "該學生可能未參加考試!"
      
        );  
    }
      
      
        else
      
      
        {  
        alert(
      
      "調用高層函數(shù)處理!"
      
        );  
        setTimeout(function(){callback();}, 1000);  
    }  
}
    
      
    

這里callback則是回調函數(shù)。可以發(fā)現(xiàn)只有當num為非負數(shù)時候callback才會調用。

但是問題,如果我們不看函數(shù)內(nèi)部,我們并不知道callback會幾時調用,在什么情況下調用,代碼間產(chǎn)生了一定耦合,流程上也會產(chǎn)生一定的混亂。

雖然回調函數(shù)是一種簡單而易于部署的實現(xiàn)異步的方法,但從編程體驗來說它卻不夠好。

  • 事件監(jiān)聽

也就是采用事件驅動,執(zhí)行順序取決于事件順序。?

      
        function
      
      
         EventTarget(){
    
      
      
        this
      
      .handlers =
      
         {};
}

EventTarget.prototype 
      
      =
      
         {
    constructor: EventTarget,
    addHandler: 
      
      
        function
      
      
        (type, handler){
        
      
      
        this
      
      .handlers[type] =
      
         [];
    },
    fire: 
      
      
        function
      
      
        (){
        
      
      
        if
      
      (!
      
        event.target){
            event.target 
      
      = 
      
        this
      
      
        ;
        }
        
      
      
        if
      
      (
      
        this
      
      .handlers[event.type 
      
        instanceof
      
      
         Array]){
            
      
      
        var
      
       handlers = 
      
        this
      
      
        .handlers[event.type];
            
      
      
        for
      
      (
      
        var
      
       i = 0, len = handlers.length, i < len; i++
      
        ){
                handlers[i](event);
            }
        }
    },
    removeHandler: 
      
      
        function
      
      
        (type, handler){
        
      
      
        if
      
      (
      
        this
      
      .handlers[type] 
      
        instanceof
      
      
         Array){
            
      
      
        var
      
       handlers = 
      
        this
      
      
        .handlers[type];
            
      
      
        for
      
      (
      
        var
      
       i = 0, le = handlers.length; i < len; i++
      
        ){
                
      
      
        if
      
      (handlers[i] ===
      
         handler){
                    
      
      
        break
      
      
        ;
                }
            }

            handlers.splice(i, 
      
      1
      
        );
        }
    }
};    
      
    

上面是《JavaScript高級程序設計》中的自定義事件實現(xiàn)。于是我們就可以通過addHandler來綁定事件處理函數(shù),用fire來觸發(fā)事件,用removeHandler來刪除事件處理函數(shù)。

雖然通過事件解耦了,但流程順序更加混亂了。

  • 鏈式異步?

個人覺得鏈式操作最值得稱贊的還是其解決了異步編程模型的執(zhí)行流程不清晰的問題。jQuery中$(document).ready就非常好的闡釋了這一理念。DOMCotentLoaded是一個事件,在DOM并未加載前,jQuery的大部分操作都不會奏效,但jQuery的設計者并沒有把他當成事件一樣來處理,而是轉成一種“選其對象,對其操作”的思路。$選擇了document對象,ready是其方法進行操作。這樣子流程問題就非常清晰了,在鏈條越后位置的方法就越后執(zhí)行。

      (
      
        function
      
      
        (){
       
      
      
        var
      
       isReady=
      
        false
      
      ; 
      
        //
      
      
        判斷onDOMReady方法是否已經(jīng)被執(zhí)行過
      
      
        var
      
       readyList= [];
      
        //
      
      
        把需要執(zhí)行的方法先暫存在這個數(shù)組里
      
      
        var
      
       timer;
      
        //
      
      
        定時器句柄
      
      
       ready=
      
        function
      
      
        (fn) {
              
      
      
        if
      
      
         (isReady )
                     fn.call( document);
              
      
      
        else
      
      
        
                     readyList.push( 
      
      
        function
      
      () { 
      
        return
      
       fn.call(
      
        this
      
      
        );});
              
      
      
        return
      
      
        this
      
      
        ;
       }
       
      
      
        var
      
       onDOMReady=
      
        function
      
      
        (){
              
      
      
        for
      
      (
      
        var
      
       i=0;i<readyList.length;i++
      
        ){
                     readyList[i].apply(document);
              }
              readyList 
      
      = 
      
        null
      
      
        ;
       }
       
      
      
        var
      
       bindReady = 
      
        function
      
      
        (evt){
              
      
      
        if
      
      (isReady) 
      
        return
      
      
        ;
              isReady
      
      =
      
        true
      
      
        ;
              onDOMReady.call(window);
              
      
      
        if
      
      
        (document.removeEventListener){
                     document.removeEventListener(
      
      "DOMContentLoaded", bindReady, 
      
        false
      
      
        );
              }
      
      
        else
      
      
        if
      
      
        (document.attachEvent){
                     document.detachEvent(
      
      "onreadystatechange"
      
        , bindReady);
                     
      
      
        if
      
      (window ==
      
         window.top){
                            clearInterval(timer);
                            timer 
      
      = 
      
        null
      
      
        ;
                     }
              }
       };
       
      
      
        if
      
      
        (document.addEventListener){
              document.addEventListener(
      
      "DOMContentLoaded", bindReady, 
      
        false
      
      
        );
       }
      
      
        else
      
      
        if
      
      
        (document.attachEvent){
              document.attachEvent(
      
      "onreadystatechange", 
      
        function
      
      
        (){
                     
      
      
        if
      
      ((/loaded|complete/
      
        ).test(document.readyState))
                            bindReady();
              });
              
      
      
        if
      
      (window ==
      
         window.top){
                     timer 
      
      = setInterval(
      
        function
      
      
        (){
                            
      
      
        try
      
      
        {
                                   isReady
      
      ||document.documentElement.doScroll('left');
      
        //
      
      
        在IE下用能否執(zhí)行doScroll判斷dom是否加載完畢
      
      
                            }
      
        catch
      
      
        (e){
                                   
      
      
        return
      
      
        ;
                            }
                            bindReady();
                     },
      
      5
      
        );
              }
       }
})();
      
    

上面的代碼不能用$(document).ready,而應該是window.ready。

  • Deferred & Promise

CommonJS中的異步編程模型也延續(xù)了這一想法,

每一個異步任務返回一個Promise對象,該對象有一個then方法,允許指定回調函數(shù)。 ?

所以我們可以這樣寫:

f1().then(f2).then(f3);

這種方法我們無需太過關注實現(xiàn),也不太需要理解異步,只要懂得通過函數(shù)選對象,通過then進行操作,就能進行異步編程。?

?

參考資料

Javascript異步編程的4種方法

jQuery鏈式操作


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 成人a毛片在线看免费全部播放 | 亚洲欧美国产另类视频 | 久久狠狠| 亚洲欧美另类专区 | 久草免费在线视频观看 | 99j久久精品久久久久久 | 日本免费的一级v一片 | 香蕉在线网站 | 国产资源在线播放 | 亚洲欧洲国产成人精品 | 91在线视频免费播放 | 北条麻妃手机在线观看 | 好吊妞免费视频 | 91在线看片一区国产 | 久久综合狠狠综合久久综合88 | 亚欧精品一区二区三区 | 91久久精品国产免费一区 | 免费看美女吃男生私人部位 | 国产一级毛片国语版 | 欧美视频第二页 | 中文字幕久久综合 | 成人深夜视频在线观看 | 九九九九精品视频在线播放 | 亚洲欧美第一页 | 亚洲偷图色综合色就色 | 四虎影视免费 | 奇米影视777色 | 久久香蕉国产线看观看精品yw | 亚洲码欧美码一区二区三区 | 欧美大屁股精品毛片视频 | 国产精品亚洲欧美大片在线看 | xoxo日本| 美女一级毛片免费观看 | 不卡猪| 免费观看一级成人毛片软件 | 奇米影视亚洲 | 天天操天天射天天 | 日本中文字幕不卡免费视频 | 欧美一级黄色毛片 | 中文字幕亚洲专区 | 毛片网站在线 |