HTML5本地存储JSON改进

3
以下是来自Guria先生回答的代码。
Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);
}

这是一个巧妙的解决方案。如何将该方案改进为“点符号”表示法?
例如,我的存储对象:
var user = { "name":"testName", "surname":"testSurname" };
localStorage.setObject("user", user);

我的目的 是通过这种方式获取名称内容。

   var name = localStorage.user.name;

我不知道JavaScript原型是如何开发的。
2个回答

2
由于您拥有setter,因此可以对存储进行足够的控制以创建您的行为。由于键/值被存储,我们可以在启动时查找上次的值,并透明地升级它们(如果需要)。使用setObject()和setItem()的好处之一是我们重新定义的属性不会妨碍重新设置新值。我仍然认为这可能会与使用localStorage的其他应用程序发生冲突,并且它将"ƒ"字符保留为特殊字符,但是如果每次使用您的setObject()方法保存对象,则以下内容运行良好:
(function() {

    function makeDot(key, value){            
        Object.defineProperty(localStorage, key, {
            configurable: true,
            enumerable: true,
              get: function() {
                  return typeof value==="string" && value.slice(0,1)==="ƒ" ? 
                       JSON.parse(value.slice(1)) : 
                       value;
             }
        });
    }

    Storage.prototype.setObject = function(key, value) {
        this.setItem(key,  "ƒ"+JSON.stringify(value));
        makeDot(key, value);
    }
     // upgrade existing object stores:   
    Object.keys(localStorage).forEach(function(a){
        var v=localStorage[a];
        if(typeof v==="string" && v.slice(0,1)==="ƒ"){
               makeDot(a, v);    
        }
    });


}());


var user = {
    "name": "testName",
    "surname": "testSurname"
};

localStorage.setObject("user", user); //save object

alert( localStorage.user.surname ); // shows: "testSurname"

点击http://jsfiddle.net/hrepekbb/查看演示。

如果您想使用点表示法来设置对象,那么您需要使用观察器或者代理反映localStorage,但这两种选择都还不够成熟。


今天我试图以相同的方式设置值。我采纳了你的建议,但不幸的是我无法通过观察者管理。你知道如何克服这个问题吗?谢谢。 - efkan
使用观察器,设置的值不会立即可用。使用setTimeout在写入后读取可能足够,但它不会像同步的localStorage那样工作得好。这意味着它在等待我们,使用观察器,我们需要等待它。如果您没有设置新的localStorage值,可以使用稍微更受支持(polyfill-able)的Object.watch(),但我认为它不像上面的代码那样“线程安全”,因此仍然需要在设置和获取之间进行小暂停。这就是为什么我没有直接设置对象的原因:正如apsillers所暗示的那样,它不起作用。 - dandavis

0

不行。存储在localStorage中的值总是JSON字符串。localStorage.getObject("user").name是你能做到的最好的。

你可以设置一个带有访问描述符的属性,充当“代理”属性。这样的代理属性映射到存储的值,但你需要为每个要访问的值都这样做。

Object.defineProperty(localStorage, "user", {
    get: function() { return localStorage.getObject("realUserKey"); },
    set: function(v) { localStorage.setObject("realUserKey", v); }
});

在这里,localStoragerealUserKey值被设置并持久化,但该值可以透明地从user属性中访问。请注意,此设置不会持久化,并且需要在每个页面加载时重新声明,就像getObjectsetObject函数一样。

再次强调:无法将此策略推广到任意键值(直到ES6标准开发完成并在浏览器中部署)。您必须显式声明每个“代理”属性。


直到今天之前,我一直认为你是正确的。我以前尝试过类似这样的东西,但总是失败了。但我失败的原因是我想用赋值语句来设置路径;使用setter方法改变了这一切,并允许重新定义每个需要它的输出,无论是即时还是提前加载。 - dandavis
谢谢你的回答,Apsillers。我已经使用了“localStorage.getObject("user").name”。不管怎样,祝你有愉快的一天。 - efkan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接