Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   setTimeout в цикле (https://javascript.ru/forum/misc/43241-settimeout-v-cikle.html)

Skoldin 28.11.2013 13:44

setTimeout в цикле
 
Добрый день! У меня есть функция анимации, проявляющая элементы и срабатывающая, когда пользователь скроллит до элемента. Появилась необходимость при срабатывании функции последовательно проявить элементы списка.

Я хотел сделать так:

var list = $('#suitable').find('li');
var timeout = 0;

for(var i = 0; i < list.length; i++) {
  setTimeout(function() {
    $(list[i]).css('opacity', 1).css('transform', 'scale(1, 1)')
  }, timeout);
  
  timeout += 250;
};


Однако, этот код не работает. Не могли бы ли вы подсказать мне, что с ним не так, и как его можно правильно переделать?

ksa 28.11.2013 13:45

Цитата:

Сообщение от Skoldin
этот код не работает

Что значит "не работает"? Если ошибка - так исправь ее...

ksa 28.11.2013 13:50

Для правильного использования значения переменной i используй такой вариант

var list = $('#suitable').find('li');
var timeout = 0;
for(var i = 0; i < list.length; i++) {
	setTimeout(
		(function (N){
			return function() {
				$(list[N]).css('opacity', 1).css('transform', 'scale(1, 1)')
			}
		})(i)
		, 
		timeout
	);
	timeout += 250;
};

Skoldin 28.11.2013 13:58

Спасибо! Правда я так и не понял, почему функция setTimeout не может использовать объявленную в цикле переменную

ruslan_mart 28.11.2013 14:25

http://learn.javascript.ru/play/Rw26Hb

<!DOCTYPE HTML>
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
    <style>
      #list > li {
        display: none;
        margin: 10px;
      }
    </style>
  </head>
  <body>
    <ul id="list">
      <li>Лист 1</li>
      <li>Лист 2</li>
      <li>Лист 3</li>
      <li>Лист 4</li>
      <li>Лист 5</li>
    </ul>

    <script>
      $(function() {
        var list = $('#list > li'),
            i = 0, show;
        
        (show = function() {
          	if(i++ > list.length) return;
          	list.eq(i).slideDown(300, show);
        })();
      });
    </script>

  </body>
</html>

ksa 28.11.2013 15:22

Цитата:

Сообщение от Skoldin
Правда я так и не понял, почему функция setTimeout не может использовать объявленную в цикле переменную

Она ее таки использует. :yes:
Только со значением, которое у нее будет на момент запуска самой функции. А не на момент выполнения собственно setTimeout()...

Skoldin 28.11.2013 15:59

Цитата:

Сообщение от Ruslan_xDD (Сообщение 283284)
http://learn.javascript.ru/play/Rw26Hb

<!DOCTYPE HTML>
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
    <style>
      #list > li {
        display: none;
        margin: 10px;
      }
    </style>
  </head>
  <body>
    <ul id="list">
      <li>Лист 1</li>
      <li>Лист 2</li>
      <li>Лист 3</li>
      <li>Лист 4</li>
      <li>Лист 5</li>
    </ul>

    <script>
      $(function() {
        var list = $('#list > li'),
            i = 0, show;
        
        (show = function() {
          	if(i++ > list.length) return;
          	list.eq(i).slideDown(300, show);
        })();
      });
    </script>

  </body>
</html>

Спасибо, но там нужен определённый эффект, с масштабированием и изменением прозрачности, а у .css() нет callback'a

Skoldin 28.11.2013 16:02

Цитата:

Сообщение от ksa (Сообщение 283302)
Она ее таки использует. :yes:
Только со значением, которое у нее будет на момент запуска самой функции. А не на момент выполнения собственно setTimeout()...

Т.е. дело в том, что i это не глобальная переменная, а локальная, принадлежащая другой функции? Я правильно понял, что тут дело в том, что вложенная функция не может изменить переменную родительской функции?

ksa 28.11.2013 16:03

Цитата:

Сообщение от Skoldin
у .css() нет callback'a

Он таки есть у animate()...

animate( параметры, [duration], [easing], [вызов] )

ksa 28.11.2013 16:06

Цитата:

Сообщение от Skoldin
Я правильно понял

Нет... :no:

К тому времени, когда истечет тот таймаут, значение переменно будет не такое, что было в момент запуска этого таймаута...

Пример

(function (){
	var i=1;
	setTimeout(function (){alert(i)},1000);
	i=10;
})();


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