前言:菜雞也有夢想,而我的夢想就是進一個真正的網際網路大廠。以前學習的時候沒有系統的整理,從今天開始要保持每週寫部落格的習慣,希望自己可以有所成長。為了培養程式設計思維,決定從設計模式開始寫起。我是通過讀《Javascript設計模式與開發實踐》來學習設計模式,並且將知識點和收穫記錄在部落格中。
此文僅記錄本人閱讀《JavaScript設計模式與開發實踐》的知識點與想法,感謝作者曾探大大寫出這麼好的一本書。如有冒犯,請聯絡本人:markcoder@outlook.com處理,請大家購買正版書籍。
1.迭代器模式介紹
迭代器模式是指提供一種方法順序訪問一個聚合物件中的各個元素,而又不需要暴露該物件 的內部表示。迭代器模式可以把迭代的過程從業務邏輯中分離出來,在使用迭代器模式之後,即 使不關心物件的內部構造,也可以按順序訪問其中的每個元素。比如 jQuery 中的$.each 函式
$.each( [1, 2, 3], function( i, n ){
console.log( '當前下標為: '+ i );
console.log( '當前值為:' + n );
});
複製程式碼
2.程式碼示例
首先我們自己先實現一個迭代器let each = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback.call(arr, i, arr[i])
}
}
each([1, 2, 3], function (i, n) {
console.log( '當前下標為: '+ i );
console.log( '當前值為:' + n );
})
複製程式碼
3.內部迭代器和外部迭代器
迭代器可以分為內部迭代器和外部迭代器,它們有各自的適用場景。3.1內部迭代器
內部迭代器就是內部已經定義好了迭代規則,它完全接手整個迭代過程,外部只需要一次初始呼叫。內部迭代器在呼叫的時候非常方便,外界不用關心迭代器內部的實現,跟迭代器的互動也僅僅是一次初始呼叫,但這也剛好是內部迭代器的缺點。由於內部迭代器的迭代規則已經被提前規定,上面的 each 函式就無法同時迭代 2 個陣列了。
比如現在有個需求,要判斷 2 個陣列裡元素的值是否完全相等, 如果不改寫 each 函式本身 的程式碼,我們能夠入手的地方似乎只剩下 each 的回撥函式了,程式碼如下:
let compare = function (ary1, ary2) {
if (ary1.length !== ary2.length) {
throw new Error('兩個陣列不相等');
}
each(ary1, function (i, n) {
if (n !== ary2[i]) {
throw new Error('兩個陣列不相等');
}
})
alert('兩個陣列相等');
}
compare([1, 2, 3], [2, 3, 4]); // throw new Error ( '兩個陣列不相等' );
複製程式碼
3.2外部迭代器
外部迭代器必須顯式地請求迭代下一個元素。外部迭代器增加了一些呼叫的複雜度,但相對也增強了迭代器的靈活性,我們可以手工控制 迭代的過程或者順序。
let Iterator = function (arr) {
let current = 0;
let next = function () {
current += 1;
}
let isDone = function () {
return current >= arr.length;
}
let getCurrentItem = function () {
return arr[current];
}
return {
next,
isDone,
getCurrentItem
}
}
let compare = function (iterator1, iterator2) {
while (!iterator1.isDone() && !iterator2.isDone()) {
if (iterator1.getCurrentItem() !== iterator2.getCurrentItem()) {
throw new Error('兩個陣列不相等');
}
iterator1.next();
iterator2.next();
}
alert('兩個陣列相等');
}
let iterator1 = Iterator([1, 2, 3]);
let iterator2 = Iterator([1, 2, 3]);
compare(iterator1, iterator2);
複製程式碼
外部迭代器雖然呼叫方式相對複雜,但它的適用面更廣,也能滿足更多變的需求。內部迭代 器和外部迭代器在實際生產中沒有優劣之分,究竟使用哪個要根據需求場景而定。
4.反向迭代器
let reverseEach = function (arr, callback) {
for (let i = arr.length - 1; i>=0; i--) {
callback.call(arr, i, arr[i]);
}
}
reverseEach([1, 2, 3], function (index, item) {
console.log(item); // 3 2 1
})
複製程式碼
5.終止迭代器
如果回撥函式的執行結果返回 false,則提前終止迴圈。let each = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback.call(arr, i, arr[i]) === false) {
break;
}
}
}
each( [ 1, 2, 3, 4, 5 ], function( i, n ){
if ( n > 3 ){ // n 大於 3 的時候終止迴圈
return false;
}
console.log( n ); // 分別輸出:1, 2, 3
});
複製程式碼