【问题标题】:Javascript function: Has half a second passed since last time you tried?Javascript 函数:自您上次尝试以来是否已经过了半秒?
【发布时间】:2011-02-09 15:35:20
【问题描述】:

我想构建一个函数,如果它在不到半秒前被调用,则返回 false。

timething.timechill=function(){
    var last
    if (last){
            if ((now.getTime()-last)>500){
                    return true
            }
            else{

                    return true
            }
    }
    else {
            last=now.getTime()
            return false
    }}

有什么想法吗?如果输入太快而无法避免溢出,我想避免 setTimeout() 并忽略输入。这是一个好习惯吗?

【问题讨论】:

  • 如果这是从您的代码复制粘贴,我会建议您不要忘记放置“;”在你的真实代码上
  • 感谢所有出色的答案!当我完全了解它们时,我会成为一个更好的 js 程序员。顺便说一句,我第一次使用这个网站。

标签: javascript time timestamp overflow


【解决方案1】:
timething.timechill = (function () {
    var lastCall = 0;
    return function () {
        if (new Date() - lastCall < 500)
            return false;
        lastCall = new Date();
        //do stuff
    }
})();

这里的想法是(function() { ... })(); 将创建一个匿名函数并立即运行它。 timething.timechill 未分配此功能。相反,它被这个函数分配了内部函数返回

请注意,lastCall 未在该内部函数中声明(使用 var 关键字)。而当外部函数返回时,lastCall 并没有消失,因为内部函数通过引用变量这一事实将其“封闭”了。

当您稍后运行timething.timechill 并遇到此变量时,它将在函数范围之外搜索该变量并找到之前声明的变量。当它返回时,变量仍然没有消失,因为它是在函数范围之外声明的。

很难清楚地解释这个概念,但它非常有用,因为lastCall 对您不需要看到它的其余代码是不可见的。

【讨论】:

  • 谢谢!我最终使用了您的代码并稍作修改。我插入了这个 else 语句: else{ lastCall = new Date();返回真; }
  • 问题是,Date() 调用会在以后引起问题吗?它只在特殊情况下被调用。基安纳卡基斯是对的吗? setTimeout 是解决这个问题的方法吗?
【解决方案2】:

我认为这不是一个好主意。根据您调用此方法的方式,它可能会导致“无限循环”行为。使用 setTimeout 您可以进行异步操作 - 在等待时间过去时不会阻塞浏览器。大多数浏览器都会检测到阻塞代码并禁用您的脚本。

【讨论】:

  • 不好是不是...如果我正确理解了setTimeout,它只是等待执行脚本对吗?如果太早,我需要“取消”它,而不是延迟它。我错过了什么吗?
【解决方案3】:

“last”变量必须存储在另一个对象中,例如全局变量的 window 对象或这里的 timething 对象。而且我从未听说过“现在”对象!?

timething.timechill = function(){

    if (!timething._last_timechill){

       if ((new Date())-timething._last_timechill >= 500) return true;
       else return false;

    } else {

        timething._last_timechill = new Date();
        return false;

   }

}

如果您愿意,可以将函数中的“timething”替换为“window”。

编辑:正如其他人指出的那样,您还可以将 _last_timechill 变量存储在闭包中。

【讨论】:

    【解决方案4】:

    您定义的函数将始终返回false,因为last 变量永远不会保存在任何地方。您可以将其作为对象的属性保存,也可以将其保存在闭包中。

    这是一个闭包示例:

    timething.timechill = (function() {
        var last = 0;
    
        function timechill() {
            var now;
    
            now = new Date().getTime();
            if (last) {
                if (now - last > 500) {
                    // It's been long enough, allow it and reset
                    last = now;
                    return true;
                }
                // Not long enough
                return false;
            }
    
            // First call
            last = now;
            return false;
        }
    
        return timechill;
    })());
    

    这使用匿名作用域函数来构建您的 timechill 函数作为 last 变量的闭包。匿名作用域函数返回对timechill 函数的引用,该函数被分配给timething.timechill。除了timechill 函数之外没有任何东西可以访问last,它完全是私有的。

    (我确信该函数的实际逻辑可以重构一下,但我认为这与您的原始逻辑非常接近,除了您返回的一个地方true 我认为您想要false。)

    这是否是一个好主意完全取决于您的用例。我不会在上面忙循环。 :-) 但是,如果您使用它来弹出类似 SO 的“您只能每 5 秒评价一次评论”之类的东西,那就没问题了,尽管在那种情况下我可能会概括它。

    【讨论】:

    • 感谢您的回答。我试图避免“堆叠”多个鼠标滚轮事件并让它们“滚动”我在这里尝试了所有解决方案,但它们都破坏了我的代码,原因是我摸不着头脑。最后你有“})());”我试图理解。 Eclipse 告诉我“左侧分配无效”,我尝试修复它并没有奏效.. 还没有
    猜你喜欢
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2013-12-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多