Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript之迭代器模式 #15

Open
Jouryjc opened this issue Aug 15, 2018 · 0 comments
Open

Javascript之迭代器模式 #15

Jouryjc opened this issue Aug 15, 2018 · 0 comments

Comments

@Jouryjc
Copy link
Owner

Jouryjc commented Aug 15, 2018

定义

迭代器模式是指提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

作用

遍历一个聚合对象,这是迭代器模式的作用。

举例

该模式的例子就数不胜数了。数组遍历方法比如Array.prototype.forEach、jQuery中的$.each()等等都是迭代器。下面自己来实现一个each函数,第一个参数是数组,第二个参数是每一步的处理函数

var each = function (arr, callback) {
    for (var i = 0, l = arr.length; i < l; i++) {
        callback.call(arr[i], i, arr[i]);
    }
}

// test
each([1,2,3], function (i ,n) {
    alert([i, n]);
});

迭代器可以分为内部迭代器和外部迭代器。上面的each函数属于内部迭代器,each函数的内部已经定义好了迭代规则,完全接手了整个过程,外部只需要调用一次。内部迭代器使用起来非常方便,就调一个函数即可,这是内部迭代器的优点。但是它只能迭代一个数组,要想迭代两个数组必须改变内部函数的实现,违反了开放-封闭原则。

而外部迭代器则必须显式的请求迭代下一个元素。外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,因为我们可以手动地控制整个迭代过程。

面试题:实现一个函数,第一次执行返回1,第二次执行返回2......这就是一个外部迭代器的案例,这道面试题也经常遇到,上菜:

var iterator = function () {
    var count = 1;
    return function () {
        console.log(count++);
    }
}

// test
var output = iterator();
output();    // 1
output();    // 2
output();    // 3
......

下面实现一个较完整的迭代器:

var Iterator = function (obj) {
    var current = 0;

    var next = function () {
        current += 1;
    };

    var isDone = function () {
        return current >= obj.length;
    };

    var getCurrItem = function () {
        return obj[current];
    };

    return {
        next: next,
        isDone: isDone,
        getCurrItem: getCurrItem,
        length: obj.length
    };
}

从上面的迭代器实现可以看出,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那么它就是迭代器。Javascript中的类数组对象也是迭代器。

倒序迭代器

顾名思义,倒序迭代器就是以倒序的方式去访问数组的每一个对象:

var reverseEach = function (arr, callback) {
    for (var l = arr.length; l >= 0; l--) {
        callback(l, arr[l]);
    }
}

// test
reverseEach([0, 1, 2], function (i ,n) {
    console.log(n);
})

中止迭代器

var each = function (arr, callback) {
    for (var i = 0, l = arr.length; i < l; i++) {
        if (callback(i, arr[i]) === false){
            break;
        }
    }
}

// test
each([1,2,3,4,5], function (i, n) {
    if (n > 3) {
        return false;
    }
    console.log(n);
});

优点

1、它支持以不同的方式遍历一个聚合对象。
2、迭代器简化了聚合类。
3、在同一个聚合上可以有多个遍历。
4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

小结

迭代器模式是一种相对简单的模式,绝大语言也内置了迭代器。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant