Javascript: создание функции с состоянием

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

function f() { 
    var state = 1;
    f = function() {
        return state++;
    };
    return f();
};

Что-то не так с этим? Если да, то какой лучший подход?

Ответ 1

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

var f = function() {
           var state = 1;
           return function() {
              return state++;
           };
        }();

Или вот другой способ:

function f() {
   return f.state++;
}
f.state = 1;

Конечно, с f.state метода f.state преимущество и недостаток (в зависимости от ваших потребностей) заключается в том, что свойство .state может быть прочитано и изменено другим кодом.

Ответ 2

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

    var statefulFunction = function() {

        // set up closure scope
        var state = 1;

        // return function with access to the closure scope
        return function() {
            return state++;
        };

    }();  // immediately execute to return function with access to closure scope

    var first = statefulFunction();  // first === 1
    var second = statefulFunction();  // second === 2

Другой шаблон - создать область закрытия и вернуть объект методам, имеющим доступ к этой области закрытия. Пример:

    var myStatefulObj = function() {

        // set up closure scope
        var state = 1;

        // return object with methods to manipulate closure scope
        return {
            incr: function() {
                state++;
            }, 
            decr: function() {
                state--;
            },
            get: function() {
                return state;
            }
        };

    }();

    myStatefulObj.incr();
    var currState = myStatefulObj.get();  // currState === 2
    myStatefulObj.decr();
    currState = myStatefulObj.get();  // currState === 1