保存/加载其状态的JavaScript对象

时间:2012-12-06 19:12:54

标签: javascript design-patterns

我想创建一个可以保存和加载其状态(到本地存储)的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();

这是一个非常简单的状态',但解决方案必须适用于具有嵌套对象,数组等的复杂状态对象,因此只需添加一个'名称'属于我的目标的财产不是我追求的目标。

4 个答案:

答案 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)

使用jQuery's extend()

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();

jsfiddle

所有归功于pimvdb。