迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而又不須要暴露該對象的內部表示。
迭代器模式能夠把迭代的過程從業務邏輯中分離出來,在使用迭代器模式以後,即便不關心對象的內部構造,也能夠按順序訪問其中的每一個元素
許多瀏覽器都支持 Javascript 的 Array.prototype.forEach
迭代器能夠分爲 內部迭代器 和 外部迭代器
1、jQuery 中的迭代器
1 $.each( [1,2,3,4], function (i, n) { 2 console.log( "當前下表爲:" + i + " , 當前值爲:" + n ); 3 });
2、自實現一個迭代器
1 // 本身實現一個數組迭代器 2 var each = function( arry, callback ){ 3 for( var i = 0, l = arry.length; i < l; i++){ 4 callback.call( arry[i], i, arry[ i ]); 5 } 6 }; 7 each([1,2,3,4], function (i, n) { 8 console.log( i + " - " + n ); // 輸出數組下標和值 9 });
3、內部迭代器
上邊的 each 函數屬於內部迭代器, each 函數內部已經定義好了迭代原則,它徹底接手整個迭代過程,外部只須要一次初始調用。
內部迭代器的優勢也恰好是它的缺點 - 使用方便,迭代交互也僅僅是一次初始調用
示例: 在不改寫 each 自己的代碼前提,實現判斷兩個數組裏元素的值是否徹底相等
1 //判斷兩個數組的值是否徹底相等 2 var compare = function( arry1, arry2){ 3 if( arry1.length !== arry2.length ){ 4 throw new Error( "arry1和arry2不相等" ); 5 } 6 each( arry1, function( i, n ){ 7 if( n !== arry2[i] ){ 8 throw new Error("arry1和arry2不相等"); 9 } 10 }); 11 console.log( "arry1和arry2相等" ); 12 }; 13 14 compare( [1,2,3,4], [1,2,3]);
4、外部迭代器
外部迭代器必須顯式地請求迭代下一個元素
外部迭代器增長了一些調用的複雜度,但相對的也加強了迭代器的靈活性,咱們能夠手工控制迭代的過程或者順序
示例: 重寫 compare
外部迭代器:
1 // 外部迭代器 2 var Iterator = function (obj) { 3 var current = 0; 4 5 var next = function(){ 6 current += 1; 7 }; 8 9 var isDone = function(){ 10 return current >= obj.length; 11 }; 12 13 var getCurrItem = function(){ 14 return obj[ current ]; 15 }; 16 17 return { 18 next: next, 19 isDone: isDone, 20 getCurrItem: getCurrItem 21 } 22 }
改寫 Compare
1 // 改寫 Compare 2 var compare = function( iterator1, iterator2 ){ 3 while( iterator1.isDone() && iterator2.isDone() ){ 4 if( iterator1.getCurrItem() !== iterator2.getCurrItem() ){ 5 throw new Error( "iterator1 和 iterator2不相等" ); 6 } 7 iterator1.next(); 8 iterator2.next(); 9 } 10 console.log( "iterator1 和 iterator2相等" ); 11 }; 12 13 var iterator1 = Iterator( [1,2,3,4] ); 14 var iterator2 = Iterator( [1,2,3,4] ); 15 16 compare(iterator1,iterator2);
5、停止迭代器
重寫 each 函數實現停止迭代
1 // 重寫 each 函數實現停止迭代 2 var each = function( arry, callback ){ 3 for( var i = 0, l = arry.length; i < l; i++ ){ 4 // callback 的執行結果返回false,提早停止迭代 5 if( callback( i, arry[i] ) === false ){ 6 break; 7 } 8 } 9 }; 10 each( [1,2,3,4,5], function ( i, n ) { 11 if( n>3 ){ // n 大於3的時候停止循環 12 return false; 13 } 14 console.log(n); // 輸出 1 2 3 15 });
6、迭代器應用示例
目的:根據不一樣的瀏覽器獲取相應的上傳組件對象
將不一樣的上傳對象封裝到各自的函數裏; 若是函數可用,則返回該對象,不然返回false,提示迭代器繼續
1 // 將不一樣的上傳對象封裝到各自的函數裏; 若是函數可用,則返回該對象,不然返回false,提示迭代器繼續 2 var getActiveUploadObj = function(){ 3 try{ 4 return new ActiceXObject( "TXFTNActiveX.FTNUpload" ); // IE 上傳控件 5 }catch(e){ 6 return false; 7 } 8 }; 9 var getFlashUploadObj = function(){ 10 if( supportFlash() ){ 11 var str = "<object type='application/x-shockwave-flash'></object>"; 12 return $( str).appendTo( $("body") ); 13 } 14 return false; 15 }; 16 var getFormUpl0adObj = function(){ 17 var str = "<input type='file' type='file' class='ui-file' />"; // 表單上傳 18 return $( str).appendTo( $("body") ); 19 };
//迭代器代碼
1 //迭代器代碼 2 var iteratorUploadObj = function(){ 3 for( var i = 0, fn; fn = arguments[ i++ ]; ){ 4 var uploadObj = fn(); 5 if( uploadObj !== false ){ 6 return uploadObj; 7 } 8 } 9 }; 10 11 var uploadObj = iteratorUploadObj( getActiveUploadObj, getFlashUploadObj, getFormUpl0adObj );
7、總結
迭代模式相對簡單,簡單到不少時候咱們不認爲它是一種設計模式
閱讀參考書籍 - << JavaScript 設計模式與開發實踐 >>