我想创建一个可以保存和加载其状态(到本地存储)的Javascript对象。
这是我使用的基本模式:
var obj = function () {
// private members
//
return {
// public members
load: function () {
this.state = JSON.parse(localStorage.getItem('obj'));
if (this.state === null) {
this.state = {
name: 'foo'
};
}
},
save: function () {
localStorage.setItem('obj', JSON.stringify(this.state));
}
};
}();
// load state
obj.load();
console.log(obj.state.name);
// save state
obj.state.name = 'bar';
obj.save();
但有一件事让我对这种模式感到恼火:我必须通过“状态”来访问对象的持久属性'属性。
如何重写这个,以便我可以更自然地使用该对象,例如:
// load state
obj.load();
console.log(obj.name);
// save state
obj.name = 'bar';
obj.save();
这是一个非常简单的状态',但解决方案必须适用于具有嵌套对象,数组等的复杂状态对象,因此只需添加一个'名称'属于我的目标的财产不是我追求的目标。
答案 0 :(得分:2)
如果你不关心加载/保存哪些属性,那么你可以简单地将所有状态复制到self中。例如,在阅读var state
之后(而不是this.state
,因为您不希望state
成为this
的一部分):for(x in state) this[x] = state[x];
同样,你要保存:var state = {}; for(x in this) state[x] = this[x]
但是,如果您想要一个预定义的列表,那么我建议:var fields = ['name', 'zip', 'age'];
然后使用for(x in fields) this[x] = state[x]
加载并for(x in fields) state[x] = this[x];
进行保存。
对不起,它有点拼凑在一起,但我希望你能按照我的意思:)
编辑:为每个OP请求添加完整示例。
使用此技术的完整解决方案示例如下:
var obj = function () {
// private members
//
return {
// public members
load: function () {
var state = JSON.parse(localStorage.getItem('obj'));
if(state == null) state = { name: 'foo' };
for(x in state) this[x] = state[x];
},
save: function ()
{
var state = {};
// check if it's a function. This version taken from underscorejs
var isFunction = function(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
};
for(x in this)
{
if(isFunction(this[x])) continue; // skip functions
state[x] = this[x];
}
localStorage.setItem('obj', JSON.stringify(state));
}
};
};
答案 1 :(得分:2)
您还可以在属性更改时完成直接保存, 使用ES5 getter / setter或使用Watch.js
Watch.js示例:
var obj = (function () {
// private members
//
var self = {
// Some properties
name: '',
otherName: '',
// Try to load state or use "foo state"
state: JSON.parse(localStorage.getItem('obj')) || {
name: 'foo'
},
save: function () {
localStorage.setItem('obj', JSON.stringify(this.state));
}
};
// Watch the object and save it to local storage, when a property changes
// (Of course, you don't need to call the save method here...)
watch(self, function(property, value) {
console.log('saving state!');
self.state[property] = value;
self.save();
});
return self;
}());
// Update some properties and see that it is saved to local storage.
obj.name = "Some name";
obj.otherName = "Some other name";
console.log(JSON.parse(localStorage.getItem('obj')));
JsFiddle上的示例。
答案 2 :(得分:0)
您可以制作state
内部和表面的getter和setter:
var obj = function () {
// private members
var state = {};
return {
// public members
load: function () {
var loadedState = JSON.parse(localStorage.getItem('obj'));
if (loadedState === null) {
state = {
name: 'foo'
};
} else {
state = loadedState;
}
},
save: function () {
localStorage.setItem('obj', JSON.stringify(state));
},
getState: function (key) {
return state[key];
},
setState: function (key, value) {
state[key] = value;
}
};
};
答案 3 :(得分:0)
var obj = (function () {
return {
load: function () {
var stored = localStorage.getItem("obj");
var state = stored ? JSON.parse(stored) : {
name: 'foo'
};
$.extend(this, state);
},
save: function () {
localStorage.setItem("obj", JSON.stringify(this));
}
};
})();
// load state
obj.load();
console.log(obj);
// save state
obj.name = 'bar';
obj.save();
所有归功于pimvdb。