来源:JavaScript设计模式与开发实践
迭代器模式是指提供一种方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
7.1 jQuery中的迭代器
迭代器模式无非就是循环访问聚合对象中的各个元素。比如 jQuery 中的$.each 函数
7.2实现迭代器
var each = function(arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback.call(arr[i], i, arr[i]);
}
};
each([1,2,3], function(i, item) {
console.log(i, item);
});
7.3内部迭代器与外部迭代器
- 内部迭代器:迭代器内部已经定义好了迭代规则,完全接收整个迭代过程。外部只需一次初始调用,无需关心内部实现。而这也正是迭代器的缺点,即迭代器的规则已经被提前规定,例如无法同时迭代两个数组进行比较。
- 外部迭代器:外部迭代器需显式请求迭代下一元素。虽然增加了复杂度,却也增加了灵活性,可以手动控制迭代过程和顺序。
//实现外部迭代器
var iterator = function(obj) {
var current = 0;
var next = function() {
current += 1;
};
var isdone = function() {
return current >= obj.length;
};
var getitem = function() {
return obj[current];
};
return {
next: next,
isdone: isdone,
getitem: getitem
};
}
var compareFun = function(iterator1, iterator2) {
while (!iterator1.isdone() && !iterator2.isdone()) {
if (iterator1.getitem() !== iterator2.getitem()) {
console.log('not same');
return;
}
iterator1.next();
iterator2.next();
}
console.log('same');
}
var iterator1 = iterator([1,2,3]);
var iterator2 = iterator([2,2,3]);
compareFun(iterator1, iterator2);
4. 迭代类数组对象和字面量对象
迭代器不仅可以迭代数组,还可以迭代一些类数组对象,如arguments,对象属性等,可发现,只要被迭代的聚合对象具有length属性并且可以用下标访问,那它就可以被迭代。
$.each = function(obj, callback) {
var value,
i = 0,
length = obj.length,
isArray = isArrayLike(obj);
if (isArray) {
for (; i < length; i++) {
value = callback.call(obj[i], i, obj[i]);
if (value === false) {
break;
}
}
} else {
for (i in obj) {
value = callback.call(obj[i], i, obj[i]);
if (value === false) {
break;
}
}
}
return obj;
}
5.倒序迭代器
var reverseFun = function(arr, callback) {
for (var i = arr.length -1; i >= 0; i--) {
callback(i, arr[i]);
}
};
reverseFun([1,2,3], function(i,item) {
console.log(i, item);
});
6.中止迭代器
迭代器可以像普通for循环中的break一样,提供一种跳出循环的方法。
var each = function(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback.call(arr[i], i, arr[i]) === false) {
break;
}
}
};
each([1,2,3,4,5,6], function(i, item) {
if (i > 3) return false;
console.log([i, item]);
});
7.7迭代器的应用举例
var getActiveUploadObj = function() {
try {
return new ActiveXObject( "TXFTNActiveX.FTNUpload" ); //IE上传控件
} catch (error) {
return false
}
};
var getFlashUploadObj = function(){
if ( supportFlash() ){ // 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') );
};
/*这三个函数都有一个共同约定,即:如果upload对象是可用的,则返回该对象,否则返回false。
则该迭代器需要: 提供一个可迭代的方法,使得三个函数按照优先级被循环迭代
如果被迭代的函数返回一个对象,则表示找到了正确的upload对象,迭代中止,反之返回false,则迭代继续
*/
iteratorUploadObj = function() {
for (var i =0, fn;fn = arguments[i++];) {
var uploadObj = fn();
if (uploadObj !== false) {
return uploadObj;
}
}
}
网友评论