Имейте функцию javascript в частном порядке, чтобы отслеживать количество вызовов - PullRequest
2 голосов
/ 24 сентября 2011

Я пытаюсь выяснить, как я могу иметь функцию 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 ]

4 голосов
/ 24 сентября 2011

Затворы - путь сюда:

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

Или, вы можете использовать насмешливый фреймворк, такой как ( бесстыдный сам вилка ) Миртл .

2 голосов
/ 24 сентября 2011

Ваша первая попытка будет работать нормально, за исключением того, что вы забыли, что 0 является ошибочным значением в JavaScript, поэтому при первом запуске и при каждом последующем запуске !this.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
# ...
1 голос
/ 24 сентября 2011

Хорошо, вот метод, который я придумал, который вообще не требует изменения функции.

Так что, если у вас есть это.

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>                                                                         

1 голос
/ 24 сентября 2011

Я на самом деле не пробовал этого, но я посмотрел «переменные статических функций в JavaScript» и обнаружил этот ресурс .Я думаю, что основное различие между тем, что вы написали, и тем, что находится в этом решении, заключается в том, как обнаруживается первый запуск функции.Возможно, ваш ! Asdf.run тест не работает так, как вы думали, и вам следует использовать typeof asdf.run == 'undefined' вместо этого.

0 голосов
/ 14 марта 2017

Вам не обязательно закрытие.Просто используйте статическую переменную.

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 */ }
0 голосов
/ 24 сентября 2011
//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
0 голосов
/ 24 сентября 2011

Итак, !asdf.run является формой оператора двойного равенства ==, и я установил asdf.run в 0, поэтому оно было ложным.

Использование тройного равенства === :

typeof asdf.run === "undefined", ибо логическое значение решает мою проблему.

Итак, последняя полезная и полезная версия:

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

Чтобы запросить количество вызовов sdf:

sdf.run;

Чтобы сделать эту переменнуючастный и защитить его от изменений, можно было бы реализовать закрытие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...