如何将'this'传递给setTimeout回调函数

9

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() this object parameter'


setTimeout()中,this指的是全局对象。你上面的代码甚至不应该对最后一项起作用。 - Kevin B
抱歉,我的代码中实际上是使用itm = $(this)而不是var itm = $(this),我已经更新了我的问题。现在我不知道该接受哪个答案了 :) - Pierre de LESPINAY
3
@PierredeLESPINAY 哦,var itmitm之间的区别在于没有var时它是一个单一的全局变量,而不是封闭函数每次调用的本地变量。这就是为什么setTimeout只看到了列表中的最后一个元素。 - Izkata
那其实就是问题所在。 - Pierre de LESPINAY
8个回答

15

@ShankarSangoli:当然可以。 - georg
如果你注意到div没有按照应有的顺序逐个淡入。 - ShankarSangoli
@ShankarSangoli我没有看到任何它不起作用的原因。请记住,这不是一个for循环,因此它没有同样的问题。 - Kevin B
1
@ShankarSangoli:这不是一个要求,至少原始代码没有这样做。 - georg
似乎无法与Bootstrap 3的工具提示一起使用?$('#elem').tooltip('show').delay(5000).tooltip('hide');隐藏似乎立即触发。 - DavidScherer

13
创建/利用闭包:
$('.item').each(function () {
  var that = this;

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

闭包

JavaScript闭包指南


由于发帖者无法使JQuery的内置工具正常工作,因此这是到目前为止最简单和最直接的方法。 - Izkata

3

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

您需要将this存储在单独的变量中:

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

2
这里的诀窍是将this保存在一个本地变量中,以便可以在setTimeout回调中安全地评估它。
$('.item').each(function () {
  var self = this;
  setTimeout(function () {
    $(self).fadeIn(1000);
  }, Math.floor(Math.random() * 1000));
});

2

试试这个:

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

2
尝试使用这个方法代替:
    $('.item').each(function () {
        var elm = this;
      setTimeout(function () {
        $(elm).fadeIn(1000);
      }, Math.floor(Math.random() * 1000));
    })

我无法解释它为什么有效,但我认为这是因为你的setTimeout中引用了另一个"this"。 http://jsfiddle.net/Pdrfz/

2

试试这个:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接