【问题标题】:Call a function only if it hasn't been called / run a function only once仅在未调用函数时调用函数/仅运行函数一次
【发布时间】:2013-06-20 22:55:57
【问题描述】:

我有一个函数animate_images 在我网站的一些页面上运行,它执行特定的动画。

我遇到的问题是,当用户再次导航到同一页面时,除了已经运行的实例之外,还会第二次调用该函数。

有没有办法做这样的事情:

if ! (animate_images) {
  animate_images();
}

基本上,我想确保animate_images 永远不会运行超过一次,无论实际调用多少次。

【问题讨论】:

  • 你可以尝试使用全局布尔值
  • 当用户加载另一个页面或重新加载相同的页面时,该功能如何仍在运行?
  • 您可以向 animate_images 添加一个 is_running 属性,在 animate_images() 函数的开头将其设置为 true ,然后在清除间隔/超时时设置为 false /动画停止。
  • 我喜欢 Paulpro 的想法,但无论你做什么,请不要使用全局布尔值。一旦你开始走这条路,你的整个应用程序就会比你想象的更快地在全局状态下运行。
  • 是的,如果你知道函数永远不会被多次实例化(不是用new 调用的),那么你可以使用函数对象的“静态”属性,如@987654329 @。我不记得了——从技术上讲,这可能使animate_images.is_running 成为全局(或与is_running 在同一范围内),而不是实际上是is_running 的属性,但效果应该是相同的。如果您使用new 实例化animate_images,那么您将使用this。 Javascript this 中的 IIRC 范围为“最近”函数实例。

标签: javascript


【解决方案1】:

看看 underscore.js 中的 once 函数 - linked here

本质上,您将函数包装在另一个内部具有标志变量的函数中。如果标志未设置,则调用该函数,并在调用时设置标志。

_.once = function(func) {
  var ran = false, memo;
  return function() {
    if (ran) return memo;
    ran = true;
    memo = func.apply(this, arguments);
    func = null;
    return memo;
};

};

如果您不想在您的网站上添加下划线(我认为这是您在启动任何网站时应该做的第一件事,但我离题了),请执行以下操作:

runOnlyOnce = function(func) {...} // As defined above

animate_images = runOnlyOnce(animate_images);

animate_images = runOnlyOnce(function(){
    alert('Animate all the things!');
});

函数本身不依赖于下划线的其余部分。

【讨论】:

  • 谢谢@Sudhir——有没有办法在我已经很重的网站上添加额外的 JS 库?
  • 是的,只要重写这个函数,给它起一个你喜欢的名字
  • 能否在您发布的@SudhirJonathan 中添加我的函数的占位符?我对 JavaScript 还很陌生,即使这也是一个挑战。应该在return memo之后吗?
  • 或者我误解了你的意思,我只需要在调用 runOnlyOnce 函数时将它放在括号内,正如你所展示的那样?
  • 是的,你也可以这样做:animate_images = runOnlyOnce(function(){alert('Images Animated');});
【解决方案2】:

使用函数对象的静态属性,如布尔值animate_images.isRunning。在animate_images开头,将动画初始化封装成类似

animate_images() {
    // on first load, animate_images.isRunning is undefined,
    //     so (!animate_images.isRunning) returns true.
    if(!animate_images.isRunning) { 
        /* launch animation */;
        // define animate_images.isRunning and assign true
        animate_images.isRunning = true;
    } else { 
        /* animation already initialized */ 
    }
}

【讨论】:

    【解决方案3】:

    你可以在函数执行后用一个空函数覆盖你的函数:

    function a(){
        console.log("hello");
        a = function(){};
    }
    
    a();  //"hello"
    a();  //>>nothing happens<<
    

    实际上,这只会覆盖对您的函数的引用 a。所以这只有在你不多次引用同一个函数时才有效。如果你这样做:

    function a(){
        console.log("hello");
        a = function(){};
    }
    
    var obj { b:a };
    
    a();  //"hello"
    a();  //>>nothing happens<<
    obj.b(); //"hello"
    

    这个方法会失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      相关资源
      最近更新 更多