20

I want to build a javascript function that maintains state. Here's a pattern that I've come up with, but something in the back of my mind tells me this is an anti-pattern.

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

Is there anything wrong with this? If so, what's a better approach?

1
  • There is nothing wrong with this technique in my book. Perfectly good example\use of a closure. Commented Nov 17, 2011 at 3:41

3 Answers 3

22

Well it's a matter of opinion what the best way is, but (although I know it works) I'm a little uncomfortable with having the function overwrite itself. A similar pattern that doesn't do that but still uses practically the same closure idea is this:

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

Or here is another way:

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

Of course with the f.state method the advantage and disadvantage (depending on your needs) is that the .state property can be read and modified by other code.

Sign up to request clarification or add additional context in comments.

1 Comment

Lazy evaluation as seen in the question enjoys application when you can't do or can't afford for performance reasons to precompute the state upon function definition. For instance, consider a function that pre-caches a DOM collection; if the function is defined before the DOM has loaded (common case), it won't work.
16

Normally, you set a closure scope and return a function that has access to that scope. Every time that function is now called, the state will remain as long as that function exists. Example:

    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

Another pattern is to create a closure scope and return an object with methods that have access to that closure scope. Example:

    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

1 Comment

looks like you are forgetting to call the myStatefulObj function to return the object
3

A better way to achieve this might be to use an Immediately-Invoked Function Expression (IIFE) to encapsulate your state.

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

console.log(f()); // 1
console.log(f()); // 2

7 Comments

I think you've misinterpreted the code in the question. It is not setting up an inner function, it is reassigning what f is, and then calling f().
Yeah I just realized that, I assumed the ; after state was a typo since JSLint has gotten me in the habit of declaring all of my variables comma delimited at the top of a function.
I'd be interested in hearing why you think this way is "better" - I think it's better too, and I included that technique as the first half of my answer, but I don't really have a good reason why it's better beyond "it seems nicer". And "seems nicer" is just a matter of opinion...
It's better because it's simpler. It's easier to reason about a function that doesn't modify itself. It's also must be easier for optimizing interpreters to optimize.
@ahnbizcad In this case since it is already a function expression (rather than a function declaration), syntactically speaking, no it is not necessary. That said it does serve a purpose when it comes to readability and code comprehension. It tells you right at the start that something more than a normal function expression is going on; you don't have to read all the way to the end of the function before you realize it is immediately invoked. To quote Douglas Crockford "...so that it is clear that the value being produced is the result of the function and not the function itself."
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.