(function(){
function Iterator(obj, name){
// Iterator(obj) and new Iterator(obj) behaviour
if(this instanceof Iterator){
var i = 0,
result = [],
skip = false,
key;
for(key in obj){
result[i++] = name ? key : [key, obj[key]];
this[key] = undefined;
if(!skip && (key == "constructor" || key == "toString" || key == "valueOf"))
skip = true;
};
// solve IE problems
for(var l = 0, arr = ["constructor", "toString", "valueOf"]; !skip && obj.hasOwnProperty && l < arr.length; l++){
if(obj.hasOwnProperty(arr[l])){
result[i++] = name ? arr[l] : [arr[l], obj[arr[l]]];
this[arr[l]] = undefined;
};
};
// add next method if any next in object
this.next = function(){
if(i === result.length)
throw new StopIteration;
else
return result[i++];
};
// reset result "pointer"
i = 0;
}
else
return new Iterator(obj, !!name);
};
function StopIteration(message, fileName, lineNumber){
this.message = message;
this.fileName = fileName;
this.lineNumber = lineNumber;
};
StopIteration.prototype = new Error;
// global scope check
if(!this.Iterator)
this.Iterator = Iterator;
if(!this.StopIteration)
this.StopIteration = StopIteration;
})();
// test it!
var iter = Iterator({a:"b", next:"c", toString:"hello"}),
output = [];
try{
while(true)
output.push(iter.next());
}
catch(err){
if(err instanceof StopIteration)
output.push("End of record");
else
output.push("Unknown error: " + err.description);
};
alert(output.join("\n"));
The best way to use them is with iter.next() method but you could use a for in loop too.
However, in latter case if the object has a next property, it will be overwrote by dynamic method but this problem apart, enjoy iterators :-)
No comments:
Post a Comment