我想用一些默认值初始化一个模块,如果需要,可以稍后更改它们。为此,我有一个包含_state
值的模块/单件。我已经公开了一个setter方法来更新该值。但是,setter不会更新_state
成员变量。代码如下所示:
var StateObject = function () {
var _state = { a: 1 };
return {
state : _state,
setState : function (s) {
_state = s;
}
};
}();
modules.export = StateObject;
和调用函数:
var SO = require('./state-object');
console.log(SO.state.a); // prints 1
SO.setState({a: 2});
console.log(SO.state.a); // still prints 1
任何人都可以解释会导致这种情况的原因以及是否有解决方法?
答案 0 :(得分:5)
像这样的解决方案的潜在缺陷是,如果某些代码在本地存储SO.state
并引用它。如果发生这种情况并且稍后调用setState()
,则该引用不会在该段代码中更新。当您替换整个州而不仅仅是州内的个人价值时,这才是您应该注意的事情。
这里的问题与引用有关。执行StateObject()
时,state
变量会存储对_state
的初始引用。然后,当您致电setState()
时,您会覆盖_state
,但state
仍然会保留之前的参考资料。
您可以尝试这样的事情:
modules.export = {
state: { a: 1 },
setState: function(v) {
this.state = v;
}
};
答案 1 :(得分:1)
嗯,问题在于引用未被更新,正如mscdex所提到的那样。
在我看来,主要的问题实际上是你的逻辑:如果你没有吸气剂,为什么要有一个吸尘器呢?
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
这很有效,因为它还返回对最新设置对象的引用。这实际上与节点或模块无关,您可以在浏览器的JavaScript控制台中运行您的示例。