setTimeout()和设置参数

时间:2011-03-02 14:38:31

标签: jquery settimeout

我有一些看起来像这样的jQuery代码:

$('.mainNav2 > li').mouseleave(function(){
    var someNum = Math.random();
    $(this).attr('id', someNum);
    var t = setTimeout("HideMenu(someNum)", 200);
    $('li.clicked').mouseenter(function() {
        clearTimeout(t);
    });
});

function HideMenu(id) {
    $('#'+id).removeClass('clicked');
}

它的目的是在鼠标离开时隐藏一个巨型菜单,但也考虑到意外的鼠标离开,使用300毫秒setTimeout。如果用户在300毫秒内将鼠标指针返回到li,则不会隐藏菜单,因为调用了clearTimout(t)。

问题是当用户意图使用mouseout时,不会调用setTimout中的函数。根据这个页面:http://www.w3schools.com/js/js_timing.asp我的语法是正确的,但如果我这样写的话,我只能从setTimeout中调用HideMenu函数:

var t = setTimeout(HideMenu, 300);

为什么它不能像写入一样工作,我可以将变量作为参数传递给函数?

6 个答案:

答案 0 :(得分:13)

要使它工作,并且不使用令人讨厌的eval版本的setTimeout更改:

var t = setTimeout("HideMenu(someNum)", 200);

到此:

var t = setTimeout(function(s) {  
                 return function() { HideMenu(s) } }(someNum), 200);

这样您就可以将someNum的值传递到s范围内的变量setTimeout

答案 1 :(得分:3)

setTimeout接受函数和毫秒延迟。该函数可以是函数引用,也可以是在超时触发时进行评估的字符串。您当前的序列如下所示:

  • mouseleave功能

    • 为变量someNum指定一个值。 someNum的范围是 当前的功能
    • 设置计时器以在200ms后评估字符串"HideNum(someNum)"
    • 结束功能,保留功能范围
  • 200ms通过

  • 评估
  • "HideNum(someNum)"。它应该抛出一个异常,因为变量some​​Num是未定义的。这就是为什么不调用HideNum的原因 - 检查控制台中的错误。

你想要的是一个函数引用,它将你的someNum保持在范围内(通过闭包 - 你可能想要阅读它)。

setTimeout(function() { 
  HideNum(someNum); 
}, 200);

您会发现Mozilla文档是JavaScript的更好参考。这是window.setTimeout文档。

答案 2 :(得分:2)

您要做的是创建一个匿名函数并在setTimeout调用中调用它。

setTimeout(function() { HideMenu(someNum) }, 200);

如果我正确理解你想做什么,你不应该为设置id和所有东西而烦恼。这样的事情应该这样做:

$('.mainNav2 > li').mouseleave(function() {
  var $this = $(this);
  var t = setTimeout(function() {
    $this.removeClass('clicked');
  }, 200);
  $('li.clicked').mouseenter(function() {
    clearTimeout(t);
  });
});

答案 3 :(得分:1)

还有更多方法可以做到这一点。

1。使用匿名函数(推荐)

setTimeout(function() {
    hideMenu('someNum');
}, 200);

2。 setTimeoutsetInterval具有隐藏功能:您可以在超时后指定参数。

setTimeout(hideMenu, 200, params);

由于你已经在使用jQuery,你不应该创建一个单独的函数,而是扩展jQuery的原型,如下所示:

jQuery.fn.hideMenu = function() {
    this.removeClass('clicked');
    return this;
};

用法:

$('#num').hideMenu();

请注意,在扩展原型时,您不需要将this传递给jQuery,因为它已经传递给jQuery。并且return this;需要保持链接的能力。

如果选择这种方式,则需要使用匿名函数,没有更简单的方法。


更新

已有一个插件:jQuery.hoverIntent()。无需亲自制作。它易于使用,只需将mouseleave事件替换为:

$('#someNum').hoverIntent(jQuery.noop, function() {
    // your function goes here
});

这样做非常重要,因为第一个是mouseenter处理程序,第二个是mouseleave处理程序。 jQuery.noop是一个空函数,它实际上与function() {}相同。

答案 4 :(得分:1)

这个工作,也可以在循环中使用。

var x = "OK";
setTimeout(alertOK.bind(null,x), 3000);
x = "Would be WRONG";
console.log("before timeout:", x);

function alertOK(x){
	console.log("after timeout:",x);
}

答案 5 :(得分:0)

因为你正在写一个字符串,它不像实际的闭包那样聪明。

$('.mainNav2 > li').mouseleave(function(){
    var someNum = Math.random();
    $(this).attr('id', someNum);
    var t = setTimeout(function() { HideMenu(someNum); }, 200);
    $('li.clicked').mouseenter(function() {
        clearTimeout(t);
    });
});

function HideMenu(id) {
    $('#'+id).removeClass('clicked');
}