JavaScript設計模式與開發實踐 迭代器模式

來源:互聯網
上載者:User

標籤:form   安裝   append   load   元素   err   調用   false   互動   

  迭代器模式是指提供一種方法順序訪問一個彙總對象中的各個元素,而又不需要暴露該對象的內部表示。迭代器模式可以把迭代的過程從商務邏輯中分離出來,在使用迭代器模式之後,即使不關心對象的內部構造,也可以按順序訪問其中的每個元素。

  一、內部迭代器和外部迭代器

  1. 內部迭代器

  內部迭代器函數的內部已經定義好了迭代規則,它完全接手整個迭代過程,外部只需要一次初始調用。

  內部迭代器在調用的時候非常方便,外界不用關心迭代器內部的實現,跟迭代器的互動也僅僅是一次初始調用,但這也剛好是內部迭代器的缺點。

    var each = function( ary, callback ){        for ( var i = 0, l = ary.length; i < l; i++ ){            callback.call( ary[i], i, ary[ i ] ); // 把下標和元素當作參數傳給callback 函數        }    };    var compare = function( iterator1, iterator2 ){        while( !iterator1.isDone() && !iterator2.isDone() ){            if ( iterator1.getCurrItem() !== iterator2.getCurrItem() ){                throw new Error ( ‘iterator1 和iterator2 不相等‘ );            }            iterator1.next();            iterator2.next();        }        alert ( ‘iterator1 和iterator2 相等‘ );    }    var iterator1 = Iterator( [ 1, 2, 3 ] );    var iterator2 = Iterator( [ 1, 2, 3 ] );    compare( iterator1, iterator2 ); // 輸出:iterator1 和iterator2 相等

 

  2. 外部迭代器

  外部迭代器必須顯式地請求迭代下一個元素。

  外部迭代器增加了一些調用的複雜度,但相對也增強了迭代器的靈活性,我們可以手工控制迭代的過程或者順序。

   //外部迭代器    var Iterator = function( obj ){        var current = 0;        var next = function(){            current += 1;        };        var isDone = function(){            return current >= obj.length;        };        var getCurrItem = function(){            return obj[ current ];        };        return {            next: next,            isDone: isDone,            getCurrItem: getCurrItem        }    };      //比較數組是否相同    var compare = function( iterator1, iterator2 ){        while( !iterator1.isDone() && !iterator2.isDone() ){            if ( iterator1.getCurrItem() !== iterator2.getCurrItem() ){                throw new Error ( ‘iterator1 和iterator2 不相等‘ );            }            iterator1.next();            iterator2.next();        }        alert ( ‘iterator1 和iterator2 相等‘ );    }    var iterator1 = Iterator( [ 1, 2, 3 ] );    var iterator2 = Iterator( [ 1, 2, 3 ] );    compare( iterator1, iterator2 ); // 輸出:iterator1 和iterator2 相等
 二、迭代類數組對象和字面量對象

  無論是內部迭代器還是外部迭代器,只要被迭代的彙總對象擁有 length 屬性而且可以用下標訪問,那它就可以被迭代。如數組、對象、arguments。

三、迭代器模式的應用舉例

  下面的方法是根據不同的瀏覽器擷取相應的上傳組件對象,因為使用瀏覽器的上傳控制項進行上傳速度快,可以暫停和續傳,所以我們首先會優先使用控制項上傳。如果瀏覽器沒有安裝上傳控制項,則使用 Flash 上傳,如果連 Flash 也沒安裝,那就只好使用瀏覽器原生的表單上傳了。

    var getUploadObj = function(){        try{            // IE 上傳控制項            return new ActiveXObject("TXFTNActiveX.FTNUpload");        }catch(e){            if ( supportFlash() ){                // supportFlash 函數未提供                var str = ‘<object type="application/x-shockwave-flash"></object>‘;                return $( str ).appendTo( $(‘body‘) );            }else{                // 表單上傳                var str = ‘<input name="file" type="file"/>‘;                return $( str ).appendTo( $(‘body‘) );            }        }    }; 

  getUploadObj 函數裡面充斥了 try,catch以及 if 條件分支。缺點是顯而易見的。第一是很難閱讀,第二是嚴重違反開閉原則。 在開發和調試過程中,我們需要來回切換不同的上傳方式,每次改動都相當痛苦。後來我們還增加支援了一些另外的上傳方式,比如,HTML5 上傳,這時候唯一的辦法是繼續往 getUploadObj 函數裡增加條件分支。

  我們把每種擷取 upload 對象的方法都封裝在各自的函數裡,然後使用一個迭代器,迭代擷取這些 upload 對象,直到擷取到一個可用的為止:

    // IE 上傳控制項    var getActiveUploadObj = function(){        try{            return new ActiveXObject( "TXFTNActiveX.FTNUpload" );          }catch(e){            return false;        }    };    // supportFlash 函數未提供    var getFlashUploadObj = function(){        if ( supportFlash() ){            var str = ‘<object type="application/x-shockwave-flash"></object>‘;              return $( str ).appendTo( $(‘body‘) );        }        return false;    };     // 表單上傳    var getFormUpladObj = function(){        var str = ‘<input name="file" type="file" class="ui-file"/>‘;         return $( str ).appendTo( $(‘body‘) );    };    //迭代器    var iteratorUploadObj = function(){        for ( var i = 0, fn; fn = arguments[ i++ ]; ){            var uploadObj = fn();            if ( uploadObj !== false ){                return uploadObj;            }        }    };    var uploadObj = iteratorUploadObj( getActiveUploadObj, getFlashUploadObj, getFormUpladObj );

 

 

  在 getActiveUploadObj 、 getFlashUploadObj 、 getFormUpladObj 這 3 個函數中都有同一個約定:如果該函數裡面的 upload 對象是可用的,則讓函數返回該對象,反之返回 false ,提示迭代器繼續往後面進行迭代。

 

JavaScript設計模式與開發實踐 迭代器模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.