Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Функция iterator (https://javascript.ru/forum/misc/27702-funkciya-iterator.html)

konstantinopol 21.04.2012 23:05

Функция iterator
 
Доброго времени суток,

учу JavaScript и наткнулся на проблемку.
Конкретнее: имеется
var Colors = ['#48AEFF', '#7FFFD4', '#C00054', '#87EF84', '#DBA7F8', '#EBC79E'];


(Color - глобальная переменная)

Нужна функция по типу итератора. При первом вызове функции возвращается первый цвет, при втором ... и т.д

Проблема в том что вне функции нельзя дефинировать переменные. Вот сижу и думаю, а как это можно сделать такую функцию без дополнительных counter за функцией? И если да как можно решить мою проблему.


Функция должна возвращать назад функцию и возможно парралельная итерация.
Бред полнейший, прошу помощи!

Зарание спасибо.

Octane 21.04.2012 23:26

var Colors = ['#48AEFF', '#7FFFD4', '#C00054', '#87EF84', '#DBA7F8', '#EBC79E'];

function getColor() {
	var fn = arguments.callee;
	if (!("lastIndex" in fn) || fn.lastIndex >= Colors.length) {
		fn.lastIndex = 0;
	}
	return Colors[fn.lastIndex++];
}

alert([getColor(), getColor(), getColor(), getColor(), getColor(), getColor(), getColor()]);



В будущем yield можно будет использовать

konstantinopol 21.04.2012 23:40

Спасибо тебе добрый человек. А можно сделать так чтобы возвращалось не значение цвета а функция. У меня есть test.js которая должна пройти без ошибок. Может с ней будет более понятно что мне нужно...
Вот она:
console.clear();
	console.log('==Color Iterator Test==');
	
	var test = function(msg, bool){
		if(bool){
			console.log("passed");
		} else {
			console.log("failed - "+msg);	
		}
	};
	
	var colorIter1 = AIS.colorIterator();
	var colorIter2 = AIS.colorIterator();
	
	test("return value not a function", typeof(colorIter1) === 'function');
	
	// two cycles
	test("color not correct", colorIter1() === '#48AEFF');
	test("color not correct", colorIter1() === '#7FFFD4');
	test("color not correct", colorIter1() === '#C00054');
	test("color not correct", colorIter1() === '#87EF84');
	test("color not correct", colorIter1() === '#DBA7F8');
	test("color not correct", colorIter1() === '#EBC79E');
	test("color not correct", colorIter1() === '#48AEFF');
	test("color not correct", colorIter1() === '#7FFFD4');
	test("color not correct", colorIter1() === '#C00054');
	test("color not correct", colorIter1() === '#87EF84');
	test("color not correct", colorIter1() === '#DBA7F8');
	test("color not correct", colorIter1() === '#EBC79E');
	
	for(var i = 0; i < 12; i++){
		test("color not correct while iterating two iterators", colorIter1() === colorIter2()); 
	};


А вот что получилось у нас за функция(ранее имена были немного другими):
var AISShipColors = ['#48AEFF', '#7FFFD4', '#C00054', '#87EF84', '#DBA7F8', '#EBC79E'];

	var colorIterator = function(){
		var fn = arguments.callee;
		if (!("lastIndex" in fn) || fn.lastIndex >= AISShipColors.length) {
			  fn.lastIndex = 0;
		 }
		return AISShipColors[fn.lastIndex++];
	};


И первое что выдаётся в консоле это "return value not a function".

Благодарю!

FINoM 21.04.2012 23:42

Octane, я думаю, лучше lastIndex задать в массиве, а не в функции, а в функцию передавать этот массив в качестве аргумента. Так функция будет универсальной для любого массива. Но это занудство. Зависит, конечно, от задачи.

konstantinopol 21.04.2012 23:44

Проблема в том что функция должна вызываться без оргументов.

Octane 21.04.2012 23:50

Ну как-то так:
var AIS = {};
var AISShipColors = ['#48AEFF', '#7FFFD4', '#C00054', '#87EF84', '#DBA7F8', '#EBC79E'];

AIS.colorIterator = function () {
	var lastIndex = 0;
	return function () {
		if (lastIndex >= AISShipColors.length) {
			lastIndex = 0;
		}
		return AISShipColors[lastIndex++];
	};
};

var colorIter1 = AIS.colorIterator();

alert([colorIter1(), colorIter1(), colorIter1(), colorIter1(), colorIter1(), colorIter1(), colorIter1()]);

Если итераторы должны зависеть друг от дурга, то просто сделайте lastIndex свойством массива, как написал FINoM

FINoM 21.04.2012 23:55

var Iterator = function( array ) { 
 this.array = array;
 this.index = -1;
 this.iterate = function() {
  return this.array[ ++this.index ] || this.array[ this.index = 0 ] 
 }
}
var iterator = new Iterator(['a', 'b', 'c', 'd', 'e']);
alert([iterator.iterate(),  iterator.iterate(),  iterator.iterate(),  iterator.iterate(),  iterator.iterate(),  iterator.iterate(),  iterator.iterate()]);

FINoM 21.04.2012 23:58

Цитата:

Сообщение от konstantinopol
А можно сделать так чтобы возвращалось не значение цвета а функция.

Что-то я не въехал в эту фразу.

konstantinopol 21.04.2012 23:59

Нет они недолжны зависеть друг от друга. Всё просто супер, спасибо тебе, большое и человеческое. У меня помимо этого ещё 4 задания поэтому, если у меня возникнут сложности я ещё напишу. Но главное ведь начало. Ещё раз спасибо!

konstantinopol 22.04.2012 00:00

Цитата:

Сообщение от FINoM (Сообщение 170440)
Что-то я не въехал в эту фразу.

Это можно уведеть в ответе Octane. Виноват, мог бы подругому описать...

FINoM 22.04.2012 00:12

В моём примере косяк в том, что, если встретится элемент массива равный 0 (==undefined==null==''==false), то вернется первый элемент и итератор зациклится до элемента, предшествующего «нулевому». Нужно допиливать условие.


Часовой пояс GMT +3, время: 23:47.