我想在HTML5 localStorage
中存储一个JavaScript对象,但我的对象显然正在转换为字符串 .
我可以使用 localStorage
存储和检索原始JavaScript类型和数组,但对象似乎不起作用 . 他们应该吗?
这是我的代码:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
console.log('typeof testObject: ' + typeof testObject);
console.log('testObject properties:');
for (var prop in testObject) {
console.log(' ' + prop + ': ' + testObject[prop]);
}
// Put the object into storage
localStorage.setItem('testObject', testObject);
// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');
console.log('typeof retrievedObject: ' + typeof retrievedObject);
console.log('Value of retrievedObject: ' + retrievedObject);
控制台输出是
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
它看起来像 setItem
方法在存储之前将输入转换为字符串 .
我在Safari,Chrome和Firefox中看到了这种行为,所以我认为这是我对HTML5 Web Storage规范的误解,而不是特定于浏览器的错误或限制 .
我试图理解http://www.w3.org/TR/html5/infrastructure.html中描述的结构化克隆算法 . 我没有't fully understand what it'说,但也许我的问题与我的对象的属性不可枚举(???)
有一个简单的解决方法吗?
更新:W3C最终改变了对结构化克隆规范的看法,并决定更改规范以匹配实现 . 见https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 . 所以这个问题不再是100%有效,但答案仍然可能是有意义的 .
27 回答
更好的是你将函数设置为setter和getter localStorage ,这样你就可以获得更好的控制,并且不必重复JSON解析等等 . 它甚至可以顺利处理你的 (" ") 空字符串键/数据包 .
使用JSON对象进行本地存储:
//组
//得到
//迭代所有本地存储密钥和值
//删除
对variant的一个小改进:
由于short-circuit evaluation,如果
key
不在存储中,getObject()
将立即返回null
. 如果value
是""
(空字符串;JSON.parse()
无法处理),它也不会抛出SyntaxError
异常 .我已经修改了一个最高投票的答案 . 如果不需要,我就是拥有单一功能而不是2的粉丝 .
此外,如果未设置任何值,则返回
null
而不是false
.false
有一些含义,null
没有 .另一种选择是使用现有的插件 .
例如persisto是一个开源项目,它为localStorage / sessionStorage提供了一个简单的接口,并自动为表单字段(输入,单选按钮和复选框)提供持久性 .
(免责声明:我是作者 . )
您可以使用localDataStorage透明地存储javascript数据类型(Array,Boolean,Date,Float,Integer,String和Object) . 它还提供轻量级数据混淆,自动压缩字符串,便于按键(名称)查询以及按(键)值查询,并通过为键添加前缀来帮助在同一域内实施分段共享存储 .
[免责声明]我是该实用程序的作者[/ DISCLAIMER]
例子:
如您所见,原始值受到尊重 .
有一个很棒的库可以包含许多解决方案,所以它甚至支持名为jStorage的旧浏览器
您可以设置一个对象
并轻松检索它
您可以使用ejson将对象存储为字符串 .
这是我使用ejson的localStorage包装器
https://github.com/UziTech/storage.js
我在包装器中添加了一些类型,包括正则表达式和函数
http://rhaboo.org是一个localStorage糖层,可以让你写这样的东西:
它不使用JSON.stringify / parse,因为这对大对象来说是不准确和缓慢的 . 相反,每个终端值都有自己的localStorage条目 .
你可能猜到我可能和rhaboo有关;-)
阿德里安 .
要存储对象,您可以创建一个字母,您可以使用这些字母将字符串中的对象转换为对象(可能没有意义) . 例如
如果你使用你用来分割对象的字母,这种技术会引起一些故障,而且它也是非常实验性的 .
对于愿意设置和获取类型属性的Typescript用户:
Example usage:
Look this
假设您有以下数组称为电影:
使用stringify函数,可以使用以下语法将movies数组转换为字符串:
请注意,我的数据存储在名为quentinTarantino的密钥下 .
检索您的数据
要将字符串转换回对象,请使用JSON解析函数:
您可以调用movies2上的所有数组方法
我想在本地,会话,cookie上避免那些问题你可以使用opendb库..
前 - 你可以解决这个问题使用此代码段
https://github.com/pankajbisht/openDB
有关Web存储的更多详细信息,请阅读web storage文章 .
您可能会发现使用这些方便的方法扩展Storage对象很有用:
这样您就可以获得您真正想要的功能,即使API下面只支持字符串 .
Stringify无法解决所有问题
似乎这里的答案并未涵盖JavaScript中可能存在的所有类型,因此这里有一些关于如何正确处理它们的简短示例:
I do not recommend 存储函数因为
eval()
是邪恶的,可能导致安全性,优化和调试方面的问题 . 通常,eval()
永远不应该在JavaScript代码中使用 .私人会员
使用
JSON.stringify()
存储对象的问题是,此函数无法序列化私有成员 . 可以通过覆盖.toString()
方法(在Web存储中存储数据时隐式调用)来解决此问题:循环引用
stringify
无法处理的另一个问题是循环引用:在此示例中,
JSON.stringify()
将抛出TypeError
"Converting circular structure to JSON" . 如果应支持存储循环引用,则可以使用JSON.stringify()
的第二个参数:但是,找到存储循环引用的有效解决方案在很大程度上取决于需要解决的任务,恢复这些数据也不是一件容易的事 .
SO已经有一些问题要处理这个问题了:Stringify (convert to JSON) a JavaScript object with circular reference
您还可以覆盖默认的Storage
setItem(key,value)
和getItem(key)
方法来处理对象/数组,就像处理任何其他数据类型一样 . 这样,您可以像往常一样简单地调用localStorage.setItem(key,value)
和localStorage.getItem(key)
.我没有对此进行过广泛的测试,但它似乎对我一直在修补的小项目没有问题 .
理论上,可以存储具有以下功能的对象:
However, Function serialization/deserialization is unreliable because it is implementation-dependent.
建议使用抽象库来实现此处讨论的许多功能以及更好的兼容性 . 很多选择:
jStorage或simpleStorage <<我的偏好
localForage
alekseykulikov/storage
Lawnchair
Store.js <<另一个不错的选择
OMG
这里是@danott发布的代码的一些扩展版本
它还将从localstorage实现 delete 值,并显示如何添加Getter和Setter层而不是
localstorage.setItem(preview, true)
你可以写
config.preview = true
好的,这里是:
那你可以用
.bind(...)
删除别名部分 . 但是我只是把它放进去,因为知道这个真的很好 . 我花了几个小时才发现为什么一个简单的get = localStorage.getItem;
不起作用循环通过本地存储
我做了一件不破坏现有存储对象的东西,但创建了一个包装器,这样你就可以做你想做的事 . 结果是一个普通的对象,没有方法,可以像任何对象一样进行访问 .
The thing I made.
如果你想要1
localStorage
属性是魔术:如果你需要几个:
你对
prop
或对象 insidestorage
所做的一切都会自动保存到localStorage
中 . 你总是玩一个真实的物体,所以你可以做这样的事情:并且将自动跟踪每个新对象 inside 跟踪对象 .
The very big downside: 这取决于
Object.observe()
所以它的浏览器支持非常有限 . 而且它很快就会为Firefox或Edge而来 .对@Guria答案的改进:
扩展Storage对象是一个很棒的解决方案 . 对于我的API,我已经为localStorage创建了一个外观,然后在设置和获取时检查它是否是一个对象 .
我用另外20行代码创建了另一个简约包装器,以允许它像它应该使用它:
https://github.com/zevero/simpleWebstorage
查看Apple,Mozilla和Microsoft文档,该功能似乎仅限于处理字符串键/值对 .
解决方法可以在存储之前对您的对象进行处理,然后在检索它时对其进行解析:
在点击另一个已经关闭的帖子后,我到达了这个帖子, Headers 是“如何在localstorage中存储数组?” . 哪个好,除非两个线程实际上都没有提供关于如何在localStorage中维护数组的完整答案 - 但是我已经设法根据两个线程中包含的信息制定解决方案 .
因此,如果其他人想要能够在数组中推送/弹出/移位项目,并且他们希望该数组存储在localStorage或sessionStorage中,那么您可以:
示例用法 - 在localStorage数组中存储简单字符串:
示例用法 - 在sessionStorage数组中存储对象:
操作数组的常用方法:
使用localStorage跟踪来自联系人的已接收消息的库的一个小示例: