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

jQuery鏈?zhǔn)讲僮?/h1>
系統(tǒng) 2441 0

兩個問題

1.jQuery的鏈?zhǔn)讲僮魇侨绾螌崿F(xiàn)的?

2.為什么要用鏈?zhǔn)讲僮鳎?

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

?

鏈?zhǔn)讲僮?

原理相信百度一下一大把,實際上鏈?zhǔn)讲僮鲀H僅是通過對象上的方法最后

return this

把對象再返回回來,對象當(dāng)然可以繼續(xù)調(diào)用方法啦,所以就可以鏈?zhǔn)讲僮髁恕D敲矗唵螌崿F(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)可鏈?zhǔn)降恼{(diào)用
      
      
D().setName("CJ").setAge(18).setName();
    

?

但……為什么要用呢?

一般的解釋:

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

例如如果沒有鏈?zhǔn)剑敲茨憧赡苄枰@樣寫代碼:

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

這個代碼中調(diào)用了兩次document.getElementById來獲取DOM樹的元素,這樣消耗比較大,而且要寫兩行,而鏈?zhǔn)街灰獙懸恍校?jié)省了代碼……

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

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

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

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

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

?例如運算3 1415926535 * 4 -? 271828182,如果設(shè)計成鏈?zhǔn)斤L(fēng)格的方法可能會是這樣的:

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

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

      
        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)雅了,和不用鏈?zhǔn)讲僮鳑]啥不同嘛!

那么如果要求是原來的BigInteger不能改變呢?好吧,鏈?zhǔn)讲僮魉坪醪荒軡M足這個需求了。

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

在設(shè)計的時候,我們需要考慮鏈?zhǔn)綆淼暮锰幒蛪奶帲驗閯e人用了鏈?zhǔn)剑跃陀面準(zhǔn)剑赡懿⒉皇且粋€很好的方案。

那么到底為什么要用鏈?zhǔn)讲僮髂兀?


為了更好的異步體驗

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

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

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

  • 回調(diào)函數(shù)?

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

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

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

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

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

  • 事件監(jiān)聽

也就是采用事件驅(qū)動,執(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高級程序設(shè)計》中的自定義事件實現(xiàn)。于是我們就可以通過addHandler來綁定事件處理函數(shù),用fire來觸發(fā)事件,用removeHandler來刪除事件處理函數(shù)。

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

  • 鏈?zhǔn)疆惒?

個人覺得鏈?zhǔn)讲僮髯钪档梅Q贊的還是其解決了異步編程模型的執(zhí)行流程不清晰的問題。jQuery中$(document).ready就非常好的闡釋了這一理念。DOMCotentLoaded是一個事件,在DOM并未加載前,jQuery的大部分操作都不會奏效,但jQuery的設(shè)計者并沒有把他當(dāng)成事件一樣來處理,而是轉(zhuǎn)成一種“選其對象,對其操作”的思路。$選擇了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,而應(yīng)該是window.ready。

  • Deferred & Promise

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

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

所以我們可以這樣寫:

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

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

?

參考資料

Javascript異步編程的4種方法

-->

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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 精品日本久久久久久久久久 | 欧美 日韩 中字 国产 | 久久爱992xxoo | 国产成人精品视频播放 | 99精品视频在线免费观看 | 国产亚洲欧美另类一区二区三区 | 神马老子不卡视频在线 | 91aaa免费观看在线观看资源 | 女人182毛片a级毛片 | 久久视频免费在线观看 | 精品亚洲一区二区三区在线播放 | 日日干日日射 | 国产欧美精品 | 美女视频免费在线观看 | 久久精品这里热有精品 | 亚洲精品98久久久久久中文字幕 | 久久国产精品免费看 | 日本人69视频jizz免费看 | 全部免费特黄特色大片视频 | 99精品国产费观看视频 | 久揄揄鲁一二三四区高清在线 | 香蕉在线影院 | 国产精品a在线观看香蕉 | 国产精品手机在线观看 | 久久6精品 | 亚洲人成自拍网站在线观看忄 | 日本高清一级做a爱过程免费视频 | 草久在线视频 | 精品动漫一区二区三区 | 美女胸又大又黄www网站 | 精品99牛牛视频 | 欧美线人一区二区三区 | 成年女人免费看片 | 久久免费手机视频 | 在线视频 自拍 | 99九九国产精品免费视频 | 香蕉视频免费看 | 日本中文字幕一区二区高清在线 | 四虎精品影院在线观看视频 | 欧美一级高清在线观看 | 亚欧成人一区二区 |