迭代器模式是一种行为设计模式,它允许您遍历集合中的元素,而无需暴露其底层表示(列表、堆栈、树等)。

简单点来说就是自己去实现一个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。

分类: JavaScript设计模式与开发实践 标签: JavaScript模式迭代器模式

评论

暂无评论数据

暂无评论数据

目录