有一个javascript函数私下跟踪它的调用次数

时间:2011-09-24 04:58:00

标签: javascript closures

我正在试图弄清楚如何让javascript函数私下跟踪它被调用的次数。目标是通过执行func.run

在调试期间在控制台中查询此值

我的第一次尝试:

function asdf() { 
  if (!asdf.run) {
    asdf.run = 0;
  } else {
    asdf.run++;
    console.error('run: ' + asdf.run);
  }
  console.error('asdf.run def: ');
  console.error(asdf.run);
}
asdf();


<小时/> 这是一个很好的教训,为什么人们总是希望在几乎所有javascript布尔值中使用===,因为他们可能秘密地==

7 个答案:

答案 0 :(得分:4)

关闭是这里的方式:

var asdf = (function () {
    var runs = 0;
    var f = function () {
        ++runs;
        // your function here
    };
    f.runs = function () {
        return runs;
    };
    return f;
}());

用法:

asdf();
asdf();
asdf.runs(); // 2
asdf();
asdf.runs(); // 3

或者,你可以使用像( shameless self plug Myrtle这样的模拟框架。

答案 1 :(得分:2)

您的第一次尝试会正常工作,除非您忘记0是JavaScript中的“虚假”值,因此在第一次运行时,此后的每次运行!this.run将评估为{{1}并且永远无法访问您的true块。这很容易解决。

else

答案 2 :(得分:1)

我实际上没有尝试过这个,但我查找了“JavaScript中的静态函数变量”,并找到了this resource。我认为你所写的内容与该解决方案中的内容之间的主要区别在于如何检测到第一次运行该函数。也许你的!asdf.run 测试没有按你想象的那样工作,你应该使用 typeof asdf.run =='undefined'进行测试。

答案 3 :(得分:1)

好的,这是我提出的一种方法,根本不需要对函数进行修改。

所以,如果你有这个。

function someFunction() {
   doingThings();
}
你可以添加这样的计数器......

addCounter(this, "someFunction");

这是您所在的范围,您可以使用任何具有您想要计算的方法的对象。

这是代码。

<html>
<head>
    <script>
        function someFunc() {
            console.log("I've been called!");
        };

        // pass an object, this or window and a function name
        function wrapFunction(parent, functionName) {
            var count = 0, orig = parent[functionName];
            parent[functionName] = function() {
                count++;
                return orig.call(this, Array.prototype.slice(arguments));
            }

            parent[functionName].getCount = function() {
                return count;
            };
        }

        var someObj = {
            someFunc: function() {
                console.log("this is someObj.someFunc()");
            }                               
        }                                   


        wrapFunction(this, "someFunc");
        wrapFunction(someObj, "someFunc");
        someFunc();           

        someObj.someFunc();
        someObj.someFunc();
        someObj.someFunc();

        console.log("Global someFunc called " + someFunc.getCount() + " time" + (someFunc.getCount() > 1 ? "s" : "")) ;
        console.log("Global someObj.someFunc called " + someObj.someFunc.getCount() + " time" + (someObj.someFunc.getCount() > 1 ? "s" : "")) ;
    </script>                                                                   
</head>                                                                         

答案 4 :(得分:0)

因此,!asdf.run是双等号运算符==的一种形式,我将asdf.run设置为0,因此它是错误的。

使用三等于===

布尔的

typeof asdf.run === "undefined"解决了我的问题。

这是一个最终可用且有用的版本:

function sdf() { 
  if (typeof sdf.run === "undefined") { sdf.run = 0; }
  sdf.run++;
}

查询被调用sdf的次数:

sdf.run;

要实际将此变量设为私有并保护其免受更改,可以实现闭包。

答案 5 :(得分:0)

//using a closure and keeping your functions out of the global scope 
var myApp = (function() {
   //counter is a private member of this scope
   var retObj = {}, counter = 0;
   //function fn() has privileged access to counter
   retObj.fn = function() {
       counter++;
       console.log(counter);
    };
    //set retObj to myApp variable
    return retObj;
}());


myApp.fn(); //count = 1
myApp.fn(); //count = 2
myApp.fn(); //count = 3

答案 6 :(得分:0)

您不一定需要关闭。只需使用静态变量。

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 */ }