让javascript函数私下跟踪它';s的电话号码

让javascript函数私下跟踪它';s的电话号码,javascript,closures,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); } as

我试图弄明白如何让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布尔语言中使用
===
,因为它们可能暗地里是
=
,所以,
!asdf.run
是双等于运算符
=
的一种形式,我已经将
asdf.run
设置为
0
,所以它是false

使用三重等于
==

typeof asdf.run==“undefined”
用于布尔值解决了我的问题

因此,最终可用且有用的版本:

function sdf() { 
  if (typeof sdf.run === "undefined") { sdf.run = 0; }
  sdf.run++;
}
要查询调用
sdf
的次数,请执行以下操作:

sdf.run;

为了使这个变量真正私有化并防止它发生变化,我们需要实现一个闭包

我实际上还没有尝试过,但我查找了“JavaScript中的静态函数变量”,发现了。我认为您编写的内容与解决方案中的内容之间的主要区别在于如何检测函数的第一次运行。也许是你的!asdf.run测试的工作方式与您想象的不一样,您应该使用typeof asdf.run==“undefined”来进行测试。

这里的方法是使用闭包:

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

或者,您可以使用类似于(无耻的自插式)的模拟框架。

您的第一次尝试可以很好地工作,除非您忘记了
0
在JavaScript中是一个“错误”值,所以在第一次运行时以及之后的每一次运行时
!此.run
将计算为
true
,而您的
else
块将永远无法到达。这很容易解决

function foo() {
  if(typeof(foo.count) == 'undefined') {
    foo.count = 0;
  } else {
    foo.count++;
  }
  console.log(foo.count);
}

foo(); # => 0
foo(); # => 1
foo(); # => 2
# ...

好的,这里有一个我提出的方法,它根本不需要修改函数

如果你有这个

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>                                                                         

函数someFunc(){
log(“我被叫过!”);
};
//传递一个对象、这个或窗口以及一个函数名
函数wrapFunction(父函数,函数名){
var count=0,orig=parent[functionName];
父级[functionName]=函数(){
计数++;
返回orig.call(这是Array.prototype.slice(参数));
}
父[functionName].getCount=函数(){
返回计数;
};
}
var someObj={
someFunc:function(){
log(“这是someObj.someFunc()”;
}                               
}                                   
wrapFunction(这是“someFunc”);
wrapFunction(someObj,someFunc);
someFunc();
someObj.someFunc();
someObj.someFunc();
someObj.someFunc();
log(“全局someFunc调用“+someFunc.getCount()+”time“+(someFunc.getCount()>1?”s):”);
log(“全局someObj.someFunc调用”+someObj.someFunc.getCount()+“时间”+(someObj.someFunc.getCount()>1?“:”);

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

var foo = function(){
    alert( ++foo.count || (foo.count = 1) );
}


// test
function callTwice(f){ f(); f(); }
callTwice(foo)                  // will alert 1 then 2

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

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

我想你忘了在帖子中包含原始函数的输出:)我不知道该接受哪个答案。我发现这篇帖子在学习javascript强制规则时很有帮助,大多数规则都是有意义的(我实际上喜欢0和“”是错误的),但肯定有一些地方会绊倒你up@DevinG Rhode-您所做的编辑很好。我之所以避免使用多个
var
语句,是因为JSLint。Doug Crockford的推理是这样的:“在具有块作用域的语言中,通常建议在第一次使用的位置声明变量。但由于JavaScript没有块作用域,因此更明智的做法是在函数顶部声明函数的所有变量。建议每个函数使用一条var语句。”
callTwice( function bar(){           
    alert( ++bar.count || (bar.count = 1) );
});                             // will alert 1 then 2
var foo = function bar(){ /* foo === bar in here */ }