本文介绍了JavaScript Iterator类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你知道一个JavaScript库,它为集合实现一个通用的Iterator类(无论是Arrays还是一些抽象的Enumerable),它具有一整套功能,比如或?

Do you know a JavaScript library that implements a generic Iterator class for collections (be it Arrays or some abstract Enumerable) with a full set of features, like the Google Common or the Apache Commons?

编辑:可枚举#each 不是Iterator类。我正在寻找一个Iterator,它可以让我们写下这样的东西:

Enumerable#each is not an Iterator class. I'm looking for an Iterator, something that would let us write something like:

var iterator = new Iterator(myCollection);
for (var element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
    // iterator 
}

编辑:mamoo提醒我们。所以现在的目标是在Javascript 1.5(ECMA 4)中找到这个Iterator函数的实现。

Edit : mamoo reminded us of the Iterator implementation in Mozilla's Javascript 1.7. So the goal now is to find an implementation of this Iterator function in Javascript 1.5 (ECMA 4).

Edit2:为什么在库(和ECMA 5)提供时使用迭代器一个每个方法?首先,因为每个通常会与这个混淆,因为回调是 call -ed(这就是为什么每个接受Prototype中的第二个参数)。然后,因为人们对(;;)构造的比对 .each(回调)更熟悉构建(至少在我的领域)。最后,因为迭代器可以遍历普通对象(参见JavaScript 1.7)。

Edit2 : Why using an iterator when libraries (and ECMA 5) provide a each method? First, because each usually messes with this because the callback is call -ed (that's why each accepts a second argument in Prototype). Then, because people are much more familiar with the for(;;) construct than with the .each(callback) construct (at least, in my field). Lastly, because an iterator can iterate over plain objects (see JavaScript 1.7).

Edit3:我接受了npup的anwser,但这是我的镜头:

Edit3 : I accepted npup's anwser, but here is my shot at it :

function Iterator(o, keysOnly) {
    if (!(this instanceof arguments.callee))
      return new arguments.callee(o, keysOnly);
    var index = 0, keys = [];
    if (!o || typeof o != "object") return;
    if ('splice' in o && 'join' in o) {
        while(keys.length < o.length) keys.push(keys.length);
    } else {
        for (p in o) if (o.hasOwnProperty(p)) keys.push(p);
    }
    this.next = function next() {
        if (index < keys.length) {
            var key = keys[index++];
            return keysOnly ? key : [key, o[key]];
        } else throw { name: "StopIteration" };
    };
    this.hasNext = function hasNext() {
        return index < keys.length;
    };
}



var lang = { name: 'JavaScript', birthYear: 1995 };  
var it = Iterator(lang);
while (it.hasNext()) {
    alert(it.next());
}
//alert(it.next()); // A StopIteration exception is thrown  


var langs = ['JavaScript', 'Python', 'C++'];  
var it = Iterator(langs);
while (it.hasNext()) {
    alert(it.next());
}
//alert(it.next()); // A StopIteration exception is thrown  


推荐答案

好的,可枚举的模式不是真正的迭代器。

Ok, the enumerable pattern is not a real iterator then.

这(下面)对你有用吗?它符合你至少给出的语义。像往常一样,在这里和那里都要做出权衡,在决定这个时候我并没有认真思考:)。$
也许你希望能够发送一两个数字以这种方式迭代一个范围。但这可能是一个开始(支持迭代哈希,数组和字符串)。

Is this (below) useful for you? It conforms to the sematics you gave at least. As usual there are tradeoffs to be made here and there, and I didn't think very hard when deciding this time :).
And maybe you would like to be able to send in a number or two and iterate over a range in that way. But this could maybe be a start (there's support for iterating over hashes, arrays and strings).

这是一个完整的演示页面,它自己运行并进行一些调试输出,但是(可能)有趣的东西在

It's a whole demo page which runs itself and does some debug output, but the (possibly) interesting stuff is in the

window.npup = (function() {
    [...]
})();

spot。

也许它只是我根本没有得到它,但你会在真实情况下使用这种类似java的迭代器?

Maybe it is just me who doesn't get it at all, but what would you use such a java-like Iterator for in a real situation?

最佳
/ npup

Best/npup

<html>
<head>
<title>untitled</title>
</head>

<body>
    <ul id="output"></ul>


<script type="text/javascript">
window.log = (function (outputAreaId) {
    var myConsole = document.getElementById(outputAreaId);
    function createElem(color) {
        var elem = document.createElement('li');
        elem.style.color = color;
        return elem;
    }
    function appendElem(elem) {
        myConsole.appendChild(elem);
    }
    function debug(msg) {
        var elem = createElem('#888');
        elem.innerHTML = msg;
        appendElem(elem);
    }
    function error(msg) {
        var elem = createElem('#f88');
        elem.innerHTML = msg;
        appendElem(elem);
    }
    return {
        debug: debug
        , error: error
    };
})('output');


window.npup = (function () {
    // Array check as proposed by Mr. Crockford
    function isArray(candidate) {
        return candidate &&
            typeof candidate==='object' &&
            typeof candidate.length === 'number' &&
            typeof candidate.splice === 'function' &&
            !(candidate.propertyIsEnumerable('length'));
    }
    function dontIterate(collection) {
        // put some checks chere for stuff that isn't iterable (yet)
        return (!collection || typeof collection==='number' || typeof collection==='boolean');
    }
    function Iterator(collection) {
        if (typeof collection==='string') {collection = collection.split('');}
        if (dontIterate(collection)) {throw new Error('Oh you nasty man, I won\'t iterate over that ('+collection+')!');}
        var arr = isArray(collection);
        var idx = 0, top=0;
        var keys = [], prop;
        if (arr) {top = collection.length;}
        else {for (prop in collection) {keys.push(prop);}}
        this.next = function () {
            if (!this.hasNext()) {throw new Error('Oh you nasty man. I have no more elements.');}
            var elem = arr ? collection[idx] : {key:keys[idx], value:collection[keys[idx]]};
            ++idx;
            return elem;
        };
        this.hasNext = function () {return arr ? idx<=top : idx<=keys.length;};
    }
    return {Iterator: Iterator};
})();

var element;

log.debug('--- Hash demo');
var o = {foo:1, bar:2, baz:3, bork:4, hepp: {a:1,b:2,c:3}, bluff:666, bluff2:777};
var iterator = new npup.Iterator(o);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
    log.debug('got elem from hash: '+element.key+' => '+element.value);
    if (typeof element.value==='object') {
        var i2 = new npup.Iterator(element.value);
        for (var e2=i2.next(); i2.hasNext(); e2=i2.next()) {
            log.debug('&nbsp;&nbsp;&nbsp;&nbsp;# from inner hash: '+e2.key+' => '+e2.value);
        }
    }
}
log.debug('--- Array demo');
var a = [1,2,3,42,666,777];
iterator = new npup.Iterator(a);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
    log.debug('got elem from array: '+ element);
}
log.debug('--- String demo');
var s = 'First the pants, THEN the shoes!';
iterator = new npup.Iterator(s);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
    log.debug('got elem from string: '+ element);
}
log.debug('--- Emptiness demo');
try {
    log.debug('Try to get next..');
    var boogie = iterator.next();
}
catch(e) {
    log.error('OW: '+e);
}

log.debug('--- Non iterables demo');
try{iterator = new npup.Iterator(true);} catch(e) {log.error('iterate over boolean: '+e);}
try{iterator = new npup.Iterator(6);} catch(e) {log.error('iterate over number: '+e);}
try{iterator = new npup.Iterator(null);} catch(e) {log.error('iterate over null: '+e);}
try{iterator = new npup.Iterator();} catch(e) {log.error('iterate over undefined: '+e);}

</script>
</body>
</html>

这篇关于JavaScript Iterator类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 13:18