2

I'd like to create a Javascript object that can save and load its state (to local storage).

This is the basic pattern I'm using:

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

But there's one thing that annoys me about this pattern: I have to access the object's persistent properties through the 'state' property.

How can I rewrite this so I can use the object in a more natural way, like:

// load state
obj.load();
console.log(obj.name);

// save state
obj.name = 'bar';
obj.save();

This is a very simple 'state', but the solution has to work for a complex state object with nested objects, arrays etc., so simply adding a 'name' property to my object is not what I'm after.

4

4 に答える 4

2

どのプロパティがロード/保存されるかを気にしない場合は、すべてを状態から自己に単純にコピーできます。たとえば、読んだ後var state(もう参加しthis.stateたくないからではなく):statethisfor(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));
        }
    };
};
于 2012-12-06T19:17:38.650 に答える
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の例。

于 2012-12-06T20:40:17.830 に答える
0

state内部および表面のゲッターとセッターを作成できます。

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;
        }
    };
};
于 2012-12-06T19:25:04.067 に答える
0

jQuery の 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 のすべての功績。

于 2012-12-06T20:01:47.247 に答える