0

I want initialize a module with some default values and change them later if required. To do this I have a module/singleton which contains a _state value. I have exposed a setter method to update that value. However, the setter does not update the _state member variable. The code looks like this:

var StateObject = function () {
    var _state = { a: 1 };
    return {
       state    : _state,
       setState : function (s) {
          _state = s;
       }
    };
}();
modules.export = StateObject;

and the calling function:

var SO = require('./state-object');
console.log(SO.state.a);  // prints 1
SO.setState({a: 2});
console.log(SO.state.a);  // still prints 1

Can anyone explain what would cause this and if there is a work around?

2 Answers 2

5

The potential pitfall of a solution like this is if some piece of code stores SO.state locally and references that. If that happens and you call setState() some time later, the reference won't be updated in that piece of code. That's just something to be aware of when you replace the whole state and not just individual values in the state.

The problem here has to do with references. When you execute StateObject(), the state variable stores the initial reference to _state. Then when you call setState(), you overwrite _state, but state is still holding on to the previous reference.

You might try something like this:

modules.export = {
  state: { a: 1 },
  setState: function(v) {
    this.state = v;
  }
};
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Especially for pointing out the pitfall up front. Short, to the point and I understand it better now.
1

Well, the problem is with the reference not being updated, as mscdex mentioned.

In my opinion the main problem is actually your logic: why have a setter if you don't have a getter?

var SO = function () {
    var _state = { a: 1 };
    return {
       getState : function () {
            return _state;
       },
       setState : function (s) {
          _state = s;
       }
    };
}();

console.log(SO.getState().a);  // prints 1
SO.setState({a: 2});
console.log(SO.getState().a);  // prints 2

This works, as it is also returning the reference to the latest set object. And this has actually nothing to do with node or modules, you can run your example in the browser's JavaScript console.

1 Comment

You make good points. A getter would imply changing a lot more code. Maybe I will do that but I still want to understand why it doesn't work - hence my reason for asking. Thanks for pointing out that it's not node specific.

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.