js设计模式之迭代器模式

转自慕课网。


迭代器是一个框架的重要设计。我们经常需要提供一种方法顺序用来处理聚合对象中各个元素,而又不暴露该对象的内部,这也是设计模式中的迭代器模式(Iterator)。



jQuery中的$.each方法就是一个典型的迭代器,通过each我们可以传入额外的function,然后来对所有的item项进行迭代操作,如下代码:


$.each([52, 97], function(index, value) {
  alert(index + ': ' + value);
});
$( "li" ).each(function( index ) {
  console.log( index + ": "" + $(this).text() );
});


针对迭代器,这里有几个特点:


? 访问一个聚合对象的内容而无需暴露它的内部。


? 为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。


? 遍历的同时更改迭代器所在的集合结构可能会导致问题。


简单的说:封装实现,然后迭代器的聚合对象不用关心迭代的过程,从而符合SRP原则。


抛开jQuery的each方法,我们自己实现一个有简单的迭代器功能的代码:


1、简单回调


function each(obj, callback) {
    var i = 0;
    var value;
    var length = obj.length;
    for (; i < length; i++) {
        callback(obj[i]);
    }
}
var arr = ['a', 'b', 'c'];
each(arr, function(name) {
    console.log(name); 
})


这样就满足了迭代模式的设计原则,对于集合内部结果常常变化各异,我们不想暴露其内部结构,但又想让客户代码透明地访问其中的元素,通过回调把逻辑给解耦出来。但是这样的处理其实太简单了,我们还要考虑至少四种情况:


? 聚合对象,可能是对象,字符串或者数组等类型


? 支持参数传递


? 支持上下文的传递


? 支持循环中退出


我们简单的修改一下上面的代码:


function each(obj, callback, context, arg) {
    var i = 0;
    var value;
    var length = obj.length;
    for (; i < length; i++) {
        callback.call(context || null, obj[i], arg);
    }
}
var arr = ['a', 'b', 'c'];
each(arr, function(name, arg) {
    console.log(name, arg ,this);
}, this, 'aaa')


当然根据回调的处理,从而判断是否要立刻中断这个循环,从而节约性能,也是很简单的,我们可以通过获取处理的返回值来处理,如下代码:


function each(obj, callback, context, arg) {
    var i = 0;
    var value;
    var length = obj.length;
    for (; i < length; i++) {
        value = callback.call(context || null, obj[i], arg);
        if (value === false) {
            break;
        }
    }


可见只要通过回调函数callback返回的ture/false的布尔值结果就可以来判断当前是否要强制退出循环。

你可能感兴趣的:(JavaScript,设计模式,jquery,迭代器)