【问题标题】:Javascript setTimeout function call with event argument?带有事件参数的Javascript setTimeout函数调用?
【发布时间】:2026-01-25 00:40:01
【问题描述】:

使用 setTimeout 时拉入事件对象的最佳方式是什么?我正在使用 jQuery 来处理所有浏览器中的事件模型的规范化,但我不确定如何将“e”对象放入 checkPos 函数中。

我当前的代码:

function MouseDownEvent(e) {
    *snip*
    timeoutID = setTimeout(checkPos(e), 500);
}
function checkPos(e) {
    //function uses e on a timeout of 500ms
    timeoutID = setTimeout( checkPos(e) }, 500);
}

目前该代码只运行一次,因为该函数在 mousedown 事件中被调用,但不会在用户移动鼠标时更新 e 对象。 FF javascript 错误控制台还声明它是“无用的 setTimeout 调用(参数周围缺少引号?)”,但遵循该建议会导致它完全失败。

如何从 setTimeout 调用中提取“e”事件参数?

编辑:添加在每 500 毫秒重新运行一次 checkPos 函数的代码中

【问题讨论】:

  • 使用您的代码,您实际上是在调用setTimeout 时调用checkPos(由于函数调用运算符())并将其返回值传递给setTimeout;该值可能不是对函数的引用,因此 setTimeout 失败。

标签: javascript jquery settimeout


【解决方案1】:

试试:

function MouseDownEvent(e) {
    *snip*
    timeoutID = setTimeout(function(){checkPos(e);}, 500);
}
function checkPos(e) {
    //function uses e on a timeout of 500ms
}

由于 OP cmets 进行编辑..

要在每次触发 checkPos 时访问更新的事件:

var myNamespace = {};

$('body').mousemove(function(e) {
    myNamespace.mouseEvent = e; 
});

function checkPos() {
    doSomethingWith(myNamespace.mouseEvent);
}

timerID = setInterval(checkPos, 500);

【讨论】:

  • 很抱歉放弃这个答案,但是当我重新运行这段代码时,将 checkPos(e); in, 每次超时后都没有引入更新的 e 事件。
  • 它不适用于您编辑的代码。此方法在e 上形成一个“闭包”。要访问更新的事件,您需要将事件存储在checkPos 函数(在其外部)可访问的某个位置,并在MouseDownEvent 函数中更新该存储的事件。
  • 没有办法在 javascript 或 jQuery 中调用事件对象,以便我可以根据超时时间拉入当前鼠标位置?
  • @C Bauer 如果您解释了为什么需要使用超时,也许会有所帮助。 Javascript 有一个用于轮询鼠标位置的 MouseMove 事件,所以我不明白您为什么要使用超时。有关更多信息,请参阅我的答案。
  • @Ollie - 该片段包含一个循环和其他代码,如果与 mousemove 事件相关联,这些代码将成为瓶颈,但它需要定期触发。
【解决方案2】:

首先,您为什么要使用两次超时?在我看来 setInterval() 会更好

function MouseDownEvent(e) {
 *snip*
 clearInterval(intervalID);
 intervalID = setInterval(function(){checkPos(e);}, 500);
}

其次,您能否澄清一下:“......但永远不要在用户移动鼠标时更新 e 对象。”为什么当用户移动鼠标时事件对象会被更新?您只分配了一个 mouseDown 处理程序。如果你想在每次鼠标移动时都做一些事情,那么你应该使用 mouseMove 事件,在这种情况下,超时/间隔无论如何都是不必要的。

function MouseMoveEvent(e) {
 //called every time the mouse is moved, event object will contain position
}

在 JavaScript 中,您应该首先寻找事件驱动的解决方案,并且仅在绝对必要时才使用定时处理程序。

*编辑 - 解决 cmets 中提出的问题 *

var handler = {
    i : 0,
    function : mouseMoveEvent(e) {
      handler.i++;
      if (handler.i % 100 == 0) {
        //Do expensive operations
      }
    }
}

$(myElement).bind("mousemove", handler.mouseMoveEvent);

【讨论】:

    【解决方案3】:

    你可以使用 curry 函数,有一个用于 jQuery here

    一般来说,你会这样:

    function foo(a, b)
    {
        alert(a + b);
    }
    
    var bar = curry(foo, 1);
    
    bar(2); // alerts 3, as if you had called foo(1, 2)
    

    所以你可以这样做:

    setTimeout(curry(checkPos, e), 500);
    

    由于 curry 返回一个函数,它的第一个参数绑定到 e,你可以直接将它传递给 setTimeout。

    【讨论】:

      【解决方案4】:

      据我所知,IE 不允许像你需要的那样传递“事件”对象。

      我能想到的唯一解决方法是将您需要的任何值预先存储为全局变量,然后在延迟函数中检查该变量。

      例如:http://jsfiddle.net/YvYtn/1/

      这将显示最后一个 X 位置,您可以从事件对象中存储您需要的任何内容。

      JS代码:

      var _lastPosX= null;
      function MouseDownEvent(evt) {
          if (typeof evt == "undefined" || !evt)
              evt = window.event;
          _lastPosX = (evt.clientX || evt.pageX);
          timeoutID = window.setTimeout("checkPos();", 500);
      }
      function checkPos() {
          alert(_lastPosX);
      }
      

      【讨论】: