Iterator pattern. ну надо же, наконец то я его попробую.
function Itr(source, onnext, startInd) {
// что будет просчитывать
this.source = source;
// при изменении указателя будет вызываться эта функция
this.onnext = typeof onnext == "function" ? onnext : function() {};
// указатель
this.index = typeof startInd == "number" ? startInd : 0;
};
Itr.prototype = {
// изменить указатель на "delta" единиц и породить псевдособытие "next"
// delta :
// >0 - вправо, <0 - влево. (сдвиг указателя)
change: function(delta) {
var ob = this;
if (ob.index + delta in ob.source) {
ob.onnext(ob.source[ob.index += delta]);
return ob.current();
} else return undefined;
},
//обёртки для change
next: function() {
return this.change(1);
},
previous: function() {
return this.change(-1)
},
// получить текущий элемент итератора
current: function() {
return this.source[this.index]
}
};
вроде организовано всё сложно, но оно всё просто, на самом деле
Itr
итерирует
не только массивы, но и пронумерованные объекты вообще.
что это такое ?
к примеру, это
obj = {
"0" : "первый член",
"1" : "второй член"
}
свойство, показывающее длину, не нужно!
Spoiler : (
проверка существования сделана отлично от цикла по массиву - я про длину).
чтобы создать итератор, можно написать так.
var myIterator = new Itr( myIterateObject/*что будет итерировать*/ );
т.е. использовать другие аргументы необязательно - обработчик псевдособытия сдвига указателя будет пустой функцией, а указатель - нулём.
функция
current
сдвигает указатель на N единиц и порождает пседособытие next.
index = index + delta
методы
next
и
current
сдвигают указатель на
1 и
-1 соответственно. (т.е. вызывают функцию change такими аргументами)
чтобы получить текущий элемент итератора, можно вызвать метод
current
.
ну и наконец, тестовые примеры
пример с использованием всех аргументов.
function Itr(a,b,c){this.source=a;this.onnext=typeof b=="function"?b:function(){};this.index=typeof c=="number"?c:0}Itr.prototype={change:function(a){if(this.index+a in this.source)return this.onnext(this.source[this.index+=a]),this.current()},next:function(){return this.change(1)},previous:function(){return this.change(-1)},current:function(){return this.source[this.index]}};
/* ------- SCRIPT END ---------*/
// что будем считать
var arr = ["слово;число", "слово1;число1", "слово2;число2"];
// откуда будем считать
// т.к. начальный указатель - нуль, а "next" немедленно передвинет указатель вправо,
// то ставим -1, чтобы при "next" он стал нулём.
var startIndex = -1;
// ваши переменные a и b
var a,b;
// обработчик псевдособытия. вызывается при изменении указателя.
// передается текущий элемент
var handler = function(current) {
var c = current.split(";");
a = c[0]; // "слово"
b = c[1]; // "число"
alert( "a = "+a+", b = "+b );
}
var ex = new Itr(arr,handler,startIndex);
// этого хватит для итерации, если всё указано :)
while( ex.next() ) ;
и пример с использованием без дополнительных аргументов.
function Itr(a,b,c){this.source=a;this.onnext=typeof b=="function"?b:function(){};this.index=typeof c=="number"?c:0}Itr.prototype={change:function(a){if(this.index+a in this.source)return this.onnext(this.source[this.index+=a]),this.current()},next:function(){return this.change(1)},previous:function(){return this.change(-1)},current:function(){return this.source[this.index]}};
/* ------- SCRIPT END ---------*/
// что будем считать
var arr = ["слово;число", "слово1;число1", "слово2;число2"];
// ваши переменные a и b
var a,b;
var ex = new Itr(arr);
// опять таки ставим индекс в минус один
ex.index = -1;
while( ex.next() ) {
var c = ex.current().split(";");
a = c[0]; // "слово"
b = c[1]; // "число"
alert( "a = "+a+", b = "+b );
}