【问题标题】:How do I find out how many times a function is called with javascript/jquery?如何找出使用 javascript/jquery 调用函数的次数?
【发布时间】:2012-01-20 23:59:34
【问题描述】:

也许是一个奇怪的问题,但它是这样的:我有一个定期调用的函数,在该函数中我需要知道我在哪个迭代中,或者该函数被调用了多少次。问题的简化版本:

jQuery( document ).ready( function(){
    setInterval( "myFunction()", 3000 );
});

function myFunction()
{
    alert( "I have been called X times" );
}

那么,我如何找出上面代码中的 X 呢?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    JS 中有一个内置函数叫做console.count()

    【讨论】:

      【解决方案2】:

      您可以使用立即调用函数表达式(或 IIFE)围绕计数器函数创建一个闭包。你可以使用 ES6 箭头函数来做到这一点:

      const counterFunction = (() => {
        let counter = 0;
        return () => console.log(++counter);
      })();
      
      counterFunction();
      counterFunction();
      counterFunction();

      或者用普通的函数表达式:

      var counterFunction = (function() {
        var counter = 0;
        return function() {
          console.log(++counter);
        };
      })();
      
      counterFunction();
      counterFunction();
      counterFunction();

      Read more about IIFEs
      Read more about closures

      【讨论】:

        【解决方案3】:

        简单版:创建一个像codeling's answer 一样的全局变量。问题 - 如果其他一些代码也定义了一个同名的全局变量,那么你们两个都有麻烦了。

        简单的扩展版本 - 给变量一个没人会使用的疯狂名称:calledTimesED7E69A7B141457CA8908A612E3D7A3A

        聪明的版本:将该变量附加到现有的全局变量。记住 - 一切都是 Javascript 中的对象!

        $(function(){ setInterval(myFunction, 3000); });
        
        function myFunction()
        {
            myFunction.calledTimes++;
            alert( "I have been called " + myFunction.calledTimes + " times" );
        }
        myFunction.calledTimes = 0;
        

        传统版本:使用范围来隐藏该变量。

        $(function()
        {
            var calledTimes = 0;
            setInterval(function()
            {
                calledTimes++;
                alert( "I have been called " + calledTimes + " times" );
            }, 3000); 
        });
        

        虽然这隐藏了“myFunction”,所以让我们用一种棘手的范围再试一次:

        var myFunction = null;
        (function()
        {
            var calledTimes = 0;
            myFunction = function()
            {
                calledTimes++;
                alert( "I have been called " + calledTimes + " times" );
            } 
        })();
        
        $(function () { setInterval(myFunction, 3000); });
        

        ... 还有无数种其他方法可以通过作用域来隐藏该变量。选择你最喜欢的。

        【讨论】:

        • 人们在这里回答问题所花费的时间和精力仍然让我感到惊讶。如果我可以将这个答案投票一千次,我会:) 感谢您提供广泛但简单解释的答案!
        【解决方案4】:

        ES6 / ES2015

        您可以使用Proxy 为您的函数使用apply() trap

        const addCounter = fn => {
          let count = 0; // keep count
        
          //define handler
          const handler = {
            apply() {
              //do something with this counter
              console.log(`I have been called ${++count} times `); 
              
              return Reflect.apply(...arguments); //call the function normally
            }
          }
          
          //wrap the function into a proxy that uses the handler and return it
          return new Proxy(fn, handler);
        }
        
        setInterval( addCounter(myFunction), 1000 );
        
        
        function myFunction() { //sample operation - move an image
          const img = document.querySelector("img");
        
          let offset = img.offsetLeft + 10;
          if (offset > 100) //return to start
            offset = 0;
            
          img.style.left = `${offset}px`;
        }
        img {
          position: absolute;
        }
        
        .as-console-wrapper {
          max-height: 45px !important;
        }
        <img src="https://picsum.photos/150" />

        【讨论】:

          【解决方案5】:

          与其他答案中的闭包或装饰器相比,静态变量更干净,也不会污染您的外部范围。

          var foo = function(){
              alert( ++foo.count || (foo.count = 1) );
          }
          
          
          // test
          function callTwice(f){ f(); f(); }
          callTwice(foo)                  // will alert 1 then 2
          

          callTwice( function bar(){           
              alert( ++bar.count || (bar.count = 1) );
          });                             // will alert 1 then 2
          

          第二个是一个命名的匿名函数。请注意以下语法:

          var foo = function bar(){ /* foo === bar in here */ }
          

          【讨论】:

            【解决方案6】:

            您必须使用闭包。 通常你会使用一个静态变量。在 Javascript 中,它看起来像:

            jQuery( document ).ready( function(){
                setInterval( myFunction, 3000 );
            });
            
            var myFunction = (function(){
                var count = 0;
                return function(){
                     count++
                     alert( "I have been called " + count + " times");
                }
            })();
            

            演示:http://jsfiddle.net/MZQ83/2/

            【讨论】:

              【解决方案7】:

              这是另一个不使用外部变量的有趣解决方案。最好的部分是您可以保持任何预先存在的功能不变,并像往常一样调用它们。这意味着如果您尝试“利用”现有库中的函数,这对您来说非常有用。它增加了一个unobtrusive计数器,让你可以继续正常调用现有的函数;即使有争论!

              // no js library required
              
              // pre-existing function
              var a = function(){
                  console.log("pre-existing function function");
                  console.log("arguments:", arguments);
              };
              
              // add counter func
              var addFnCounter = function(target){
                  var swap = target;
                  var count = 0;
                  return function(){
                      swap.apply(null, arguments);
                      count++;
                      console.log("func has been called " + count + " times");
                      console.log("\n");
                  };
              };
              
              // usage
              a = addFnCounter(a);
              
              // call a() as you would normally
              a();
              a(1,2,3);
              a('hello', 'world');
              
              // using your setInterval example
              setInterval(a, 3000);
              

              输出

              pre-existing function function
              arguments: []
              func has been called 1 times
              
              pre-existing function function
              arguments: [1, 2, 3]
              func has been called 2 times
              
              pre-existing function function
              arguments: ["hello", "world"]
              func has been called 3 times
              

              setInterval 输出

              pre-existing function function
              arguments: []
              func has been called 4 times
              
              pre-existing function function
              arguments: []
              func has been called 5 times
              
              pre-existing function function
              arguments: []
              func has been called 6 times
              

              See it working here on jsfiddle

              【讨论】:

              • 对于任何想知道的人来说,一个函数接受另一个函数并返回一个修改后的版本被称为 装饰器
              【解决方案8】:

              您可以简单地使用一个全局变量,每次调用该函数时该变量都会增加:

              var myFuncCalls = 0;
              
              function myFunction()
              {
                  myFuncCalls++;
                  alert( "I have been called " + myFuncCalls + " times" );
              }
              

              一旦您的代码变得有点复杂(或者如果您使用许多其他库),您应该考虑使用此处其他答案中所示的范围(最好在 one by Vilx 中解释)。

              【讨论】:

              • 即使该函数位于单独的文件中,这也能工作吗?该函数是否具有 myFunCalls 变量的“知识”?
              • 在这种情况下,最好在单独的文件中声明变量,它将在“主”文档中可见。我不是 100% 确定反过来
              • 是的,所有的 javascript 文件在执行之前都在主文档中进行了“复制粘贴”。因此它们都共享相同的全局变量和所有内容。这就是为什么在创建全局变量时要始终小心的原因 - 如果两个脚本创建了相同的全局变量,它们会相互影响工作。
              • 是的。不过在这种情况下不是问题。
              • @FoadFarkhondeh 您应该非常小心这样的解决方案,因为全局命名空间污染通常是一种不好的做法。
              【解决方案9】:

              创建一个全局变量并初始化为零。然后在调用 myfunction() 时加一。显示该变量而不是 X

              【讨论】:

                猜你喜欢
                • 2010-11-07
                • 1970-01-01
                • 2010-10-03
                • 1970-01-01
                • 1970-01-01
                • 2011-01-30
                • 1970-01-01
                • 2014-07-02
                相关资源
                最近更新 更多