Как я могу отслеживать несколько запусков одной и той же функции? - PullRequest
2 голосов
/ 04 февраля 2011

У меня есть такая функция:

function run(arg) {
    if (!window.alreadyRun) init();
    window.alreadyRun = true;
    /* more code */
}

Вы поняли, я пытаюсь выяснить, вызывается ли функция впервые.

Есть ли лучший способ сделать это? Без использования глобалов? Как то так:

function run(arg) {
    var ranAlready;
    if (!ranAlready) init();
    ranAlready = true;
    /* more code */
}

Ответы [ 4 ]

5 голосов
/ 04 февраля 2011

Это вернет функцию с переменной с именем runCount, которая будет содержать количество вызовов, которое она вызывала.

var yourFunction = function() {
    var runCount = 0;

    return function() {
        console.log(runCount);
        runCount++;
    }  

}

var a = yourFunction();

a(); // runCount: 0
a(); // runCount: 1
a(); // runCount: 2
a(); // runCount: 3

См. На jsFiddle .

Если вы просто хотите запустить функцию типа init, вы можете поместить код выше, возвращая внутреннюю функцию. Он будет вызван один раз перед возвратом внутренней функции, и его область действия сохранит свою внешнюю функцию.

2 голосов
/ 04 февраля 2011

Сила замыканий.

var f = (function(run) {
    return function() {
        if (!run) init(),run=true;
        // do code
    };
}(false));

Вы даже можете использовать if (!run) init() && run = true и получить init для возврата false, если хотите, чтобы он вызывался снова при следующем вызове функции.

У нас есть самопроизвольная функция, которая создает локальную переменную run и устанавливает ее равной false, передавая ее в качестве аргумента. Затем у нас есть одна строка, которая проверяет, является ли false, если да, то init(), run=true, которая выполняет функцию init и присваивает ей значение true в одном выражении.

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

Если вам нужна переменная, статическая для функции и доступная только для чтения, вы можете использовать малоизвестное ключевое слово const.

1 голос
/ 04 февраля 2011

Я думаю, что замыкания полностью излишни для этого и только усложняют код.

То, что вы описываете, известно как статическая переменная в объектно-ориентированных языках, и ее можно легко имитировать в JS, прикрепляя свойства непосредственно к функции. Это возможно, потому что функции являются первоклассными объектами в JS:

function run(arg) {
    if (!run.ranAlready) { // run.ranAlready is undefined at first, so falsy
       run.ranAlready = true;
       init();
    }

    /* more code */
}

Это намного проще, чем вложенные функции, и вы можете продолжать использовать run() точно таким же образом.

Еще одним преимуществом является то, что для модульного тестирования вы все равно можете получить доступ к свойству ranAlready из-за пределов функции, чтобы проверить, что ваш код работает правильно:

assert(run.runAlready == false);
run();
assert(run.runAlready === true);

Конечно, это нельзя использовать для анонимных функций, например, в обработчиках событий, но не намного ли лучше, если присвоит этой анонимной функции имя вместо использования вложенных функций и дополнительной функции призывание

0 голосов
/ 04 февраля 2011

Вот еще один способ сделать это. Вы можете изменить функцию. В приведенном ниже случае myfunction изменяется на новый. Это может не совсем то, что вы ищете, но я думаю, что полезно хотя бы опубликовать это, чтобы вы могли увидеть альтернативные способы сделать что-то (а также: самоизменяющийся код иногда может быть просто крут) .

var myfunction = function() {
    alert("This is the first time I'm executed");

    myfunction = function() {
        alert('Subsequent times');
    }
}

myfunction();  // displays the alert 'This is the first time...'
myfunction();  // displays the alert 'Subsequent times'
myfunction();

Пример: http://jsfiddle.net/jonathon/wntmB/

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