JavaScript 迭代器模式
迭代器模式是一种行为设计模式,它允许您遍历集合中的元素,而无需暴露其底层表示(列表、堆栈、树等)。
简单点来说就是自己去实现一个for循环。
var each = function( ary, callback ){
for ( var i = 0, l = ary.length; i < l; i++ ){
callback.call( ary[i], i, ary[ i ] ); // 把下标和元素当作参数传给 callback 函数
}
};
each( [ 1, 2, 3 ], function( i, n ){
alert ( [ i, n ] );
});
迭代器也分为内部迭代器和外部迭代器,其中内部迭代器就是就是内部定义好了迭代规则,比如预设的forEach循环,外部不关心它是怎么实现的,只需要正常的去使用。
但是内部迭代器的优点也是它的缺点,由于无法定制化,内部迭代器的灵活性不够,于是有的外部迭代器,外部迭代器必须显示的请求迭代下一个元素,我们因此可以手动控制迭代的过程和顺序。
在es6中有规范规定了迭代器的实现。迭代器协议要求对象必须实现一个 next()
方法,该方法返回一个带有两个属性的对象:
- value:迭代过程中当前位置的值。
- done:一个布尔值,表示迭代是否结束。
这个规范允许 JavaScript 开发人员创建可迭代对象,例如数组、字符串和 Map,并使用相同的语法 (例如 for...of
循环) 来遍历它们。
这种外部的实现就是外部迭代器。
当然有时候不一定非要按照ES6的规则去实现迭代器,我们可以自己约束一个规则,以书中这个代码为例:
var getUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE 上传控件
} 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
方法就会变的越来越庞大,里面的if else语句怕是越来越多,这显然不够健壮。
我们可以利用迭代器的方式来改善这段代码,我们约束:如果迭代的时候返回的对象不是false,就表示使用该上传的手段,如果是false,则继续迭代下一个。
var getActiveUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE 上传控件
} catch (e) {
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'));
};
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);
这也是一种用法,这和我之前在项目里写的适配器模式最后的用法类似,我当时写了5个适配器,需要一个地方去使用这5个适配器,当时我就约束,每个适配器类会有一个静态方法,用于告知是否能使用该适配器,然后也是创建了一个数组存放适配器,然后while循环,每次循环调用静态类的方法,直到方法返回的值是true。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据