Как передать this в обратный вызов setTimeout - PullRequest
9 голосов
/ 06 февраля 2012

CSS

.item {
  display: none;
}

HTML

<div>
  <div class="item">machin</div>
  <div class="item">chose</div>
  <div class="item">chouette</div>
  <div class="item">prout</div>
</div>

Я использую jQuery, и я хотел бы, чтобы каждый .item появлялся после случайного небольшого таймера, например:

Javascript

$('.item').each(function () {
  itm = $(this);
  setTimeout(function () {
    itm.fadeIn(1000);
  }, Math.floor(Math.random() * 1000));
})

Здесь itm всегда будет содержать последний элемент, поскольку функция оценивается после всех назначений.
Я не могу использовать третий параметр setTimeout(), потому что он не будет работать в IE.
Из соображений безопасности не рекомендуется использовать setTimeout() с eval .

Так как я могу получить доступ к своему объекту через setTimeout()?


Редактировать

Я знаю, что этот вопрос уже был опубликован.
Но я подумал, что это было немного специфично с контекстом each().
Теперь кто-то полностью изменил заголовок моего вопроса, который изначально был что-то вроде 'setTimeout () - jQuery.each () этот параметр объекта'

Ответы [ 8 ]

15 голосов
/ 06 февраля 2012

Не используйте setTimeout, используйте собственные инструменты jQuery.

$('.item').each(function () {
   $(this).delay(Math.random() * 1000).fadeIn();
})

http://api.jquery.com/delay/

Рабочий пример: http://jsfiddle.net/qENhd/

13 голосов
/ 06 февраля 2012

Создание / использование closure:

$('.item').each(function () {
  var that = this;

  setTimeout(function () {
    $(that).fadeIn(1000);
  }, Math.floor(Math.random() * 1000));
})

http://jibbering.com/faq/notes/closures/

https://developer.mozilla.org/en/JavaScript/Guide/Closures

3 голосов
/ 06 февраля 2012

Прежде чем setTimeout выполнит цикл each завершится, он не будет ждать. Также внутри setTimeout функция this не будет ссылаться на элемент DOM.

Попробуйте что-то вроде этого.

function fadeItem(item){
   item.fadeIn(1000);
}

$('.item').each(function () {
  var $item = $(this);
  setTimeout(function () {
    fadeItem($item);
  }, Math.floor(Math.random() * 1000));
});

Вы также можете попробовать что-то вроде этого.

var $items = $('.item'), count = 0;

function fadeItem(item){
   item.fadeIn(1000);
    if(count < $items.length){
       setTimeout(function(){
            fadeItem($items.eq(count++));
       }, Math.floor(Math.random() * 1000));
    }
}
setTimeout(function(){
    fadeItem($items.eq(count++));
}, Math.floor(Math.random() * 1000));
2 голосов
/ 06 февраля 2012

Попробуйте это:

 $('.item').each(function () {
    var item =$(this);
    setTimeout(function () {
            item.fadeIn(1000);
        },
        Math.floor(Math.random() * 1000));
   });
2 голосов
/ 06 февраля 2012

Попробуйте это застраховано:

    $('.item').each(function () {
        var elm = this;
      setTimeout(function () {
        $(elm).fadeIn(1000);
      }, Math.floor(Math.random() * 1000));
    })

Я не могу объяснить, почему это работает, но я думаю, что это ссылка на другое "это" в вашем setTimeout.

http://jsfiddle.net/Pdrfz/

2 голосов
/ 06 февраля 2012

Попробуйте это:

$('.item').each(function () {
 var myVar = $(this);
setTimeout(function () {
myVar.fadeIn(1000);
}, Math.floor(Math.random() * 1000));
})
2 голосов
/ 06 февраля 2012

Хитрость здесь в том, чтобы сохранить this в локальном, что можно безопасно оценить в setTimeout обратном вызове

$('.item').each(function () {
  var self = this;
  setTimeout(function () {
    $(self).fadeIn(1000);
  }, Math.floor(Math.random() * 1000));
});
2 голосов
/ 06 февраля 2012

Вам нужно хранить this в отдельной переменной:

$('.item').each(function () {
  var me = $(this);
  setTimeout(function () {
    me.fadeIn(1000);
  }, Math.floor(Math.random() * 1000));
})
...