[英]How to store objects in HTML5 localStorage/sessionStorage
I'd like to store a JavaScript object in HTML5 localStorage
, but my object is apparently being converted to a string.我想将 JavaScript object 存储在 HTML5
localStorage
中,但我的 object 显然正在转换为字符串。
I can store and retrieve primitive JavaScript types and arrays using localStorage
, but objects don't seem to work.我可以使用
localStorage
存储和检索原始类型 JavaScript 和 arrays,但对象似乎不起作用。 Should they?他们应该吗?
Here's my code:这是我的代码:
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);
The console output is控制台 output 是
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
It looks to me like the setItem
method is converting the input to a string before storing it.在我看来,
setItem
方法在存储之前将输入转换为字符串。
I see this behavior in Safari, Chrome, and Firefox, so I assume it's my misunderstanding of the HTML5 Web Storage specification, not a browser-specific bug or limitation.我在 Safari、Chrome 和 Firefox 中看到了这种行为,所以我假设这是我对HTML5 Web 存储规范的误解,而不是特定于浏览器的错误或限制。
I've tried to make sense of the structured clone algorithm described in 2 Common infrastructure .我试图理解2 Common infrastructure中描述的结构化克隆算法。 I don't fully understand what it's saying, but maybe my problem has to do with my object's properties not being enumerable (???).
我不完全明白它在说什么,但也许我的问题与我的对象的属性不可枚举有关(???)。
Is there an easy workaround?有简单的解决方法吗?
Update: The W3C eventually changed their minds about the structured-clone specification, and decided to change the spec to match the implementations.更新:W3C 最终改变了他们对结构化克隆规范的看法,并决定更改规范以匹配实现。 See 12111 – spec for Storage object getItem(key) method does not match implementation behavior .
请参见12111 – 存储规范 object getItem(key) 方法与实现行为不匹配。 So this question is no longer 100% valid, but the answers still may be of interest.
所以这个问题不再是 100% 有效,但答案仍然很有趣。
Looking at the Apple , Mozilla and Mozilla again documentation, the functionality seems to be limited to handle only string key/value pairs.再次查看Apple 、 Mozilla和Mozilla文档,该功能似乎仅限于处理字符串键/值对。
A workaround can be to stringify your object before storing it, and later parse it when you retrieve it:一种解决方法是在存储对象之前对其进行字符串化,然后在检索时对其进行解析:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');
console.log('retrievedObject: ', JSON.parse(retrievedObject));
A minor improvement on a variant :一个变体的小改进:
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);
}
Because of short-circuit evaluation , getObject()
will immediately return null
if key
is not in Storage.由于短路评估,如果
key
不在 Storage 中, getObject()
将立即返回null
。 It also will not throw a SyntaxError
exception if value
is ""
(the empty string; JSON.parse()
cannot handle that).如果
value
""
(空字符串; JSON.parse()
无法处理),它也不会抛出SyntaxError
异常。
You might find it useful to extend the Storage object with these handy methods:您可能会发现使用这些方便的方法扩展 Storage 对象很有用:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(this.getItem(key));
}
This way you get the functionality that you really wanted even though underneath the API only supports strings.通过这种方式,您可以获得您真正想要的功能,即使在 API 下仅支持字符串。
Creating a facade for the Storage object is an awesome solution.为 Storage 对象创建外观是一个很棒的解决方案。 That way, you can implement your own
get
and set
methods.这样,您可以实现自己的
get
和set
方法。 For my API, I have created a facade for localStorage and then check if it is an object or not while setting and getting.对于我的 API,我为 localStorage 创建了一个外观,然后在设置和获取时检查它是否是一个对象。
var data = {
set: function(key, value) {
if (!key || !value) {return;}
if (typeof value === "object") {
value = JSON.stringify(value);
}
localStorage.setItem(key, value);
},
get: function(key) {
var value = localStorage.getItem(key);
if (!value) {return;}
// assume it is an object that has been stringified
if (value[0] === "{") {
value = JSON.parse(value);
}
return value;
}
}
It seems that the answers here don't cover all types that are possible in JavaScript, so here are some short examples on how to deal with them correctly:似乎这里的答案并没有涵盖 JavaScript 中所有可能的类型,所以这里有一些关于如何正确处理它们的简短示例:
// Objects and Arrays:
var obj = {key: "value"};
localStorage.object = JSON.stringify(obj); // Will ignore private members
obj = JSON.parse(localStorage.object);
// Boolean:
var bool = false;
localStorage.bool = bool;
bool = (localStorage.bool === "true");
// Numbers:
var num = 42;
localStorage.num = num;
num = +localStorage.num; // Short for "num = parseFloat(localStorage.num);"
// Dates:
var date = Date.now();
localStorage.date = date;
date = new Date(parseInt(localStorage.date));
// Regular expressions:
var regex = /^No\.[\d]*$/i; // Usage example: "No.42".match(regex);
localStorage.regex = regex;
var components = localStorage.regex.match("^/(.*)/([a-z]*)$");
regex = new RegExp(components[1], components[2]);
// Functions (not recommended):
function func() {}
localStorage.func = func;
eval(localStorage.func); // Recreates the function with the name "func"
I do not recommend to store functions, because eval()
is evil and can lead to issues regarding security, optimisation and debugging.我不建议存储函数,因为
eval()
是邪恶的,可能会导致有关安全、优化和调试的问题。
In general, eval()
should never be used in JavaScript code.一般来说,
eval()
永远不应该在 JavaScript 代码中使用。
The problem with using JSON.stringify()
for storing objects is, that this function can not serialise private members.使用
JSON.stringify()
存储对象的问题是,这个函数不能序列化私有成员。
This issue can be solved by overwriting the .toString()
method (which is called implicitly when storing data in web storage):这个问题可以通过覆盖
.toString()
方法(在 Web 存储中存储数据时隐式调用)来解决:
// Object with private and public members:
function MyClass(privateContent, publicContent) {
var privateMember = privateContent || "defaultPrivateValue";
this.publicMember = publicContent || "defaultPublicValue";
this.toString = function() {
return '{"private": "' + privateMember + '", "public": "' + this.publicMember + '"}';
};
}
MyClass.fromString = function(serialisedString) {
var properties = JSON.parse(serialisedString || "{}");
return new MyClass(properties.private, properties.public);
};
// Storing:
var obj = new MyClass("invisible", "visible");
localStorage.object = obj;
// Loading:
obj = MyClass.fromString(localStorage.object);
Another problem stringify
can't deal with are circular references: stringify
无法处理的另一个问题是循环引用:
var obj = {};
obj["circular"] = obj;
localStorage.object = JSON.stringify(obj); // Fails
In this example, JSON.stringify()
will throw a TypeError
"Converting circular structure to JSON" .在这个例子中,
JSON.stringify()
将抛出一个TypeError
"Converting circular structure to JSON" 。
If storing circular references should be supported, the second parameter of JSON.stringify()
might be used:如果应该支持存储循环引用,可以使用
JSON.stringify()
的第二个参数:
var obj = {id: 1, sub: {}};
obj.sub["circular"] = obj;
localStorage.object = JSON.stringify(obj, function(key, value) {
if(key == 'circular') {
return "$ref" + value.id + "$";
} else {
return value;
}
});
However, finding an efficient solution for storing circular references highly depends on the tasks that need to be solved, and restoring such data is not trivial either.但是,找到存储循环引用的有效解决方案在很大程度上取决于需要解决的任务,并且恢复此类数据也并非易事。
There are already some question on Stack Overflow dealing with this problem: Stringify (convert to JSON) a JavaScript object with circular reference Stack Overflow 上已经有一些关于处理这个问题的问题: Stringify (convert to JSON) a JavaScript object with circular reference
I arrived at this post after hitting on another post that has been closed as a duplicate of this - titled 'how to store an array in localstorage?'.我在点击另一个已关闭的帖子后到达此帖子 - 标题为“如何在本地存储中存储数组?”。 Which is fine except neither thread actually provides a full answer as to how you can maintain an array in localStorage - however I have managed to craft a solution based on information contained in both threads.
这很好,除了两个线程实际上都没有提供关于如何在 localStorage 中维护数组的完整答案 - 但是我已经设法根据两个线程中包含的信息制定了一个解决方案。
So if anyone else is wanting to be able to push/pop/shift items within an array, and they want that array stored in localStorage or indeed sessionStorage, here you go:因此,如果其他人希望能够在数组中推送/弹出/移动项目,并且他们希望将该数组存储在 localStorage 或实际上是 sessionStorage 中,那么您可以:
Storage.prototype.getArray = function(arrayName) {
var thisArray = [];
var fetchArrayObject = this.getItem(arrayName);
if (typeof fetchArrayObject !== 'undefined') {
if (fetchArrayObject !== null) { thisArray = JSON.parse(fetchArrayObject); }
}
return thisArray;
}
Storage.prototype.pushArrayItem = function(arrayName,arrayItem) {
var existingArray = this.getArray(arrayName);
existingArray.push(arrayItem);
this.setItem(arrayName,JSON.stringify(existingArray));
}
Storage.prototype.popArrayItem = function(arrayName) {
var arrayItem = {};
var existingArray = this.getArray(arrayName);
if (existingArray.length > 0) {
arrayItem = existingArray.pop();
this.setItem(arrayName,JSON.stringify(existingArray));
}
return arrayItem;
}
Storage.prototype.shiftArrayItem = function(arrayName) {
var arrayItem = {};
var existingArray = this.getArray(arrayName);
if (existingArray.length > 0) {
arrayItem = existingArray.shift();
this.setItem(arrayName,JSON.stringify(existingArray));
}
return arrayItem;
}
Storage.prototype.unshiftArrayItem = function(arrayName,arrayItem) {
var existingArray = this.getArray(arrayName);
existingArray.unshift(arrayItem);
this.setItem(arrayName,JSON.stringify(existingArray));
}
Storage.prototype.deleteArray = function(arrayName) {
this.removeItem(arrayName);
}
example usage - storing simple strings in localStorage array:示例用法 - 在 localStorage 数组中存储简单字符串:
localStorage.pushArrayItem('myArray','item one');
localStorage.pushArrayItem('myArray','item two');
example usage - storing objects in sessionStorage array:示例用法 - 在 sessionStorage 数组中存储对象:
var item1 = {}; item1.name = 'fred'; item1.age = 48;
sessionStorage.pushArrayItem('myArray',item1);
var item2 = {}; item2.name = 'dave'; item2.age = 22;
sessionStorage.pushArrayItem('myArray',item2);
common methods to manipulate arrays:操作数组的常用方法:
.pushArrayItem(arrayName,arrayItem); -> adds an element onto end of named array
.unshiftArrayItem(arrayName,arrayItem); -> adds an element onto front of named array
.popArrayItem(arrayName); -> removes & returns last array element
.shiftArrayItem(arrayName); -> removes & returns first array element
.getArray(arrayName); -> returns entire array
.deleteArray(arrayName); -> removes entire array from storage
Using JSON objects for local storage: 使用JSON对象进行本地存储:
//SET //组
var m={name:'Hero',Title:'developer'};
localStorage.setItem('us', JSON.stringify(m));
//GET //得到
var gm =JSON.parse(localStorage.getItem('us'));
console.log(gm.name);
// Iteration of all local storage keys and values //迭代所有本地存储键和值
for (var i = 0, len = localStorage.length; i < len; ++i) {
console.log(localStorage.getItem(localStorage.key(i)));
}
// DELETE //删除
localStorage.removeItem('us');
delete window.localStorage["us"];
In theory, it is possible to store objects with functions:理论上,可以使用函数存储对象:
function store (a)
{
var c = {f: {}, d: {}};
for (var k in a)
{
if (a.hasOwnProperty(k) && typeof a[k] === 'function')
{
c.f[k] = encodeURIComponent(a[k]);
}
}
c.d = a;
var data = JSON.stringify(c);
window.localStorage.setItem('CODE', data);
}
function restore ()
{
var data = window.localStorage.getItem('CODE');
data = JSON.parse(data);
var b = data.d;
for (var k in data.f)
{
if (data.f.hasOwnProperty(k))
{
b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");
}
}
return b;
}
However, function serialization/deserialization is unreliable because it is implementation-dependent .但是,函数序列化/反序列化是不可靠的,因为它是依赖于实现的。
You could also override the default Storage setItem(key,value)
and getItem(key)
methods to handle objects/arrays like any other data type. 您还可以覆盖默认的Storage
setItem(key,value)
和getItem(key)
方法,以像处理任何其他数据类型一样处理对象/数组。 That way, you can simply call localStorage.setItem(key,value)
and localStorage.getItem(key)
as you normally would. 这样,您可以像往常一样简单地调用
localStorage.setItem(key,value)
和localStorage.getItem(key)
。
I haven't tested this extensively, but it has appeared to work without problems for a small project I've been tinkering with. 我没有对此进行广泛的测试,但是对于我一直在修补的一个小项目,它似乎可以正常工作。
Storage.prototype._setItem = Storage.prototype.setItem;
Storage.prototype.setItem = function(key, value)
{
this._setItem(key, JSON.stringify(value));
}
Storage.prototype._getItem = Storage.prototype.getItem;
Storage.prototype.getItem = function(key)
{
try
{
return JSON.parse(this._getItem(key));
}
catch(e)
{
return this._getItem(key);
}
}
It is recommended using an abstraction library for many of the features discussed here, as well as better compatibility.建议对这里讨论的许多特性使用抽象库,以及更好的兼容性。 There are lots of options:
有很多选择:
You can use localDataStorage to transparently store JavaScript data types (Array, Boolean, Date, Float, Integer, String and Object).您可以使用localDataStorage透明地存储 JavaScript 数据类型(Array、Boolean、Date、Float、Integer、String 和 Object)。 It also provides lightweight data obfuscation, automatically compresses strings, facilitates query by key (name) as well as query by (key) value, and helps to enforce segmented shared storage within the same domain by prefixing keys.
它还提供轻量级的数据混淆,自动压缩字符串,促进键(名称)查询和(键)值查询,并通过为键加前缀来帮助在同一域内强制执行分段共享存储。
[DISCLAIMER] I am the author of the utility [/DISCLAIMER] [免责声明] 我是该实用程序的作者 [/DISCLAIMER]
Examples:例子:
localDataStorage.set( 'key1', 'Belgian' )
localDataStorage.set( 'key2', 1200.0047 )
localDataStorage.set( 'key3', true )
localDataStorage.set( 'key4', { 'RSK' : [1,'3',5,'7',9] } )
localDataStorage.set( 'key5', null )
localDataStorage.get( 'key1' ) // --> 'Belgian'
localDataStorage.get( 'key2' ) // --> 1200.0047
localDataStorage.get( 'key3' ) // --> true
localDataStorage.get( 'key4' ) // --> Object {RSK: Array(5)}
localDataStorage.get( 'key5' ) // --> null
As you can see, the primitive values are respected.如您所见,原始值受到尊重。
You cannot store a key value without a string format.您不能存储没有字符串格式的键值。
LocalStorage only supports string formats for keys/values. LocalStorage仅支持键/值的字符串格式。
That is why you should convert your data to string whatever it is an array or object.这就是为什么您应该将数据转换为字符串,无论它是数组还是对象。
To store data in localStorage, first of all stringify it using the JSON.stringify() method.要将数据存储在 localStorage 中,首先使用 JSON.stringify() 方法对其进行字符串化。
var myObj = [{name:"test", time:"Date 2017-02-03T08:38:04.449Z"}];
localStorage.setItem('item', JSON.stringify(myObj));
Then when you want to retrieve data, you need to parse the string to object again.然后当你想检索数据时,你需要再次将字符串解析为对象。
var getObj = JSON.parse(localStorage.getItem('item'));
Better you make functions as setter and getter to localStorage , this way you will have better control and won't have to repeat the JSON parsing and all. 更好的是,将函数设置为localStorage的 setter和getter,这样,您将可以更好地控制并且不必重复JSON解析等等。 it will even handle your (" ") empty string key/data case smoothly.
它甚至可以顺利处理您的(“”)空字符串键/数据大小写。
function setItemInStorage(dataKey, data){
localStorage.setItem(dataKey, JSON.stringify(data));
}
function getItemFromStorage(dataKey){
var data = localStorage.getItem(dataKey);
return data? JSON.parse(data): null ;
}
setItemInStorage('user', { name:'tony stark' });
getItemFromStorage('user'); /* return {name:'tony stark'} */
I've modified one of top-voted answer a little. 我修改了投票最多的答案之一。 I'm a fan of having single function instead of 2 if it's not needed.
我喜欢单一功能而不是2(如果不需要)。
Storage.prototype.object = function(key, val) {
if ( typeof val === "undefined" ) {
var value = this.getItem(key);
return value ? JSON.parse(value) : null;
} else {
this.setItem(key, JSON.stringify(val));
}
}
localStorage.object("test", {a : 1}); //set value
localStorage.object("test"); //get value
Also, if no value is set, it's returning null
instead of false
. 另外,如果未设置任何值,则返回
null
而不是false
。 false
has some meaning, null
does not. false
具有某些含义, null
没有含义。
You can use ejson to store the objects as strings.您可以使用ejson将对象存储为字符串。
EJSON is an extension of JSON to support more types.
EJSON 是 JSON 的扩展,支持更多类型。 It supports all JSON-safe types, as well as:
它支持所有 JSON 安全类型,以及:
- Date (JavaScript
Date
)日期(JavaScript
Date
)- Binary (JavaScript
Uint8Array
or the result of EJSON.newBinary )二进制(JavaScript
Uint8Array
或EJSON.newBinary的结果)- User-defined types (see EJSON.addType . For example, Mongo.ObjectID is implemented this way.)
用户定义的类型(见EJSON.addType 。例如, Mongo.ObjectID就是这样实现的。)
All EJSON serializations are also valid JSON.
所有 EJSON 序列化也是有效的 JSON。 For example an object with a date and a binary buffer would be serialized in EJSON as:
例如,带有日期和二进制缓冲区的对象将在 EJSON 中序列化为:
{ "d": {"$date": 1358205756553}, "b": {"$binary": "c3VyZS4="} }
Here is my localStorage wrapper using ejson这是我使用 ejson 的 localStorage 包装器
https://github.com/UziTech/storage.js https://github.com/UziTech/storage.js
I added some types to my wrapper including regular expressions and functions我在包装器中添加了一些类型,包括正则表达式和函数
Improvement on @Guria 's answer: @Guria的答案的改进:
Storage.prototype.setObject = function (key, value) {
this.setItem(key, JSON.stringify(value));
};
Storage.prototype.getObject = function (key) {
var value = this.getItem(key);
try {
return JSON.parse(value);
}
catch(err) {
console.log("JSON parse failed for lookup of ", key, "\n error was: ", err);
return null;
}
};
Another option would be to use an existing plugin.另一种选择是使用现有的插件。
For example persisto is an open source project that provides an easy interface to localStorage/sessionStorage and automates persistence for form fields (input, radio buttons, and checkboxes).例如, persisto是一个开源项目,它为 localStorage/sessionStorage 提供了一个简单的接口,并自动化了表单字段(输入、单选按钮和复选框)的持久性。
(Disclaimer: I am the author.) (免责声明:我是作者。)
For TypeScript users willing to set and get typed properties:对于愿意设置和获取类型化属性的 TypeScript 用户:
/**
* Silly wrapper to be able to type the storage keys
*/
export class TypedStorage<T> {
public removeItem(key: keyof T): void {
localStorage.removeItem(key);
}
public getItem<K extends keyof T>(key: K): T[K] | null {
const data: string | null = localStorage.getItem(key);
return JSON.parse(data);
}
public setItem<K extends keyof T>(key: K, value: T[K]): void {
const data: string = JSON.stringify(value);
localStorage.setItem(key, data);
}
}
// write an interface for the storage
interface MyStore {
age: number,
name: string,
address: {city:string}
}
const storage: TypedStorage<MyStore> = new TypedStorage<MyStore>();
storage.setItem("wrong key", ""); // error unknown key
storage.setItem("age", "hello"); // error, age should be number
storage.setItem("address", {city:"Here"}); // ok
const address: {city:string} = storage.getItem("address");
https://github.com/adrianmay/rhaboo is a localStorage sugar layer that lets you write things like this: https://github.com/adrianmay/rhaboo是一个 localStorage 糖层,可让您编写如下内容:
var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
one: ['man', 'went'],
2: 'mow',
went: [ 2, { mow: ['a', 'meadow' ] }, {} ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');
It doesn't use JSON.stringify/parse because that would be inaccurate and slow on big objects.它不使用 JSON.stringify/parse ,因为这在大对象上会不准确且速度慢。 Instead, each terminal value has its own localStorage entry.
相反,每个终端值都有自己的 localStorage 条目。
You can probably guess that I might have something to do with rhaboo.您可能会猜到我可能与 rhaboo 有关。
localStorage.setItem('obj',JSON.stringify({name:'Akash'})); // Set Object in localStorage
localStorage.getItem('obj'); // Get Object from localStorage
sessionStorage.setItem('obj',JSON.stringify({name:'Akash'})); // Set Object in sessionStorage
sessionStorage.getItem('obj'); // Get Object from sessionStorage
I made another minimalistic wrapper with only 20 lines of code to allow using it like it should:我制作了另一个只有 20 行代码的简约包装器,以允许像应有的那样使用它:
localStorage.set('myKey',{a:[1,2,5], b: 'ok'});
localStorage.has('myKey'); // --> true
localStorage.get('myKey'); // --> {a:[1,2,5], b: 'ok'}
localStorage.keys(); // --> ['myKey']
localStorage.remove('myKey');
https://github.com/zevero/simpleWebstorage https://github.com/zevero/simpleWebstorage
A small example of a library that use localStorage for keeping track of received messages from contacts: 一个使用localStorage跟踪来自联系人的消息的库的小示例:
// This class is supposed to be used to keep a track of received message per contacts.
// You have only four methods:
// 1 - Tells you if you can use this library or not...
function isLocalStorageSupported(){
if(typeof(Storage) !== "undefined" && window['localStorage'] != null ) {
return true;
} else {
return false;
}
}
// 2 - Give the list of contacts, a contact is created when you store the first message
function getContacts(){
var result = new Array();
for ( var i = 0, len = localStorage.length; i < len; ++i ) {
result.push(localStorage.key(i));
}
return result;
}
// 3 - store a message for a contact
function storeMessage(contact, message){
var allMessages;
var currentMessages = localStorage.getItem(contact);
if(currentMessages == null){
var newList = new Array();
newList.push(message);
currentMessages = JSON.stringify(newList);
}
else
{
var currentList =JSON.parse(currentMessages);
currentList.push(message);
currentMessages = JSON.stringify(currentList);
}
localStorage.setItem(contact, currentMessages);
}
// 4 - read the messages of a contact
function readMessages(contact){
var result = new Array();
var currentMessages = localStorage.getItem(contact);
if(currentMessages != null){
result =JSON.parse(currentMessages);
}
return result;
}
Here is some extended version of the code posted by danott :这是danott 发布的代码的一些扩展版本:
It'll also implement a delete value from localstorage and shows how to adds a Getter and Setter layer so instead of,它还将从 localstorage 中实现一个删除值,并展示如何添加一个 Getter 和 Setter 层,而不是,
localstorage.setItem(preview, true)
you can write你可以写
config.preview = true
Okay, here were go:好的,开始了:
var PT=Storage.prototype
if (typeof PT._setItem >='u')
PT._setItem = PT.setItem;
PT.setItem = function(key, value)
{
if (typeof value >='u') //..undefined
this.removeItem(key)
else
this._setItem(key, JSON.stringify(value));
}
if (typeof PT._getItem >='u')
PT._getItem = PT.getItem;
PT.getItem = function(key)
{
var ItemData = this._getItem(key)
try
{
return JSON.parse(ItemData);
}
catch(e)
{
return ItemData;
}
}
// Aliases for localStorage.set/getItem
get = localStorage.getItem.bind(localStorage)
set = localStorage.setItem.bind(localStorage)
// Create ConfigWrapperObject
var config = {}
// Helper to create getter & setter
function configCreate(PropToAdd){
Object.defineProperty( config, PropToAdd, {
get: function () { return (get(PropToAdd) )},
set: function (val) { set(PropToAdd, val)}
})
}
//------------------------------
// Usage Part
// Create properties
configCreate('preview')
configCreate('notification')
//...
// Configuration Data transfer
// Set
config.preview = true
// Get
config.preview
// Delete
config.preview = undefined
Well, you may strip the aliases part with .bind(...)
.好吧,您可以使用
.bind(...)
别名部分。 However, I just put it in since it's really good to know about this.但是,我只是把它放进去,因为知道这一点真的很好。 I took me hours to find out why a simple
get = localStorage.getItem;
我花了几个小时来找出为什么一个简单的
get = localStorage.getItem;
don't work.不工作。
I made a thing that doesn't break the existing Storage objects, but creates a wrapper so you can do what you want.我做了一个不会破坏现有存储对象的东西,而是创建了一个包装器,这样你就可以做你想做的事了。 The result is a normal object, no methods, with access like any object.
结果是一个普通对象,没有方法,可以像任何对象一样访问。
If you want 1 localStorage
property to be magic:如果您希望 1
localStorage
属性具有魔力:
var prop = ObjectStorage(localStorage, 'prop');
If you need several:如果你需要几个:
var storage = ObjectStorage(localStorage, ['prop', 'more', 'props']);
Everything you do to prop
, or the objects inside storage
will be automatically saved into localStorage
.您对
prop
或storage
中的对象所做的一切都会自动保存到localStorage
中。 You're always playing with a real object, so you can do stuff like this:你总是在玩一个真实的对象,所以你可以做这样的事情:
storage.data.list.push('more data');
storage.another.list.splice(1, 2, {another: 'object'});
And every new object inside a tracked object will be automatically tracked.并且被跟踪对象内的每个新对象都将被自动跟踪。
The very big downside: it depends on Object.observe()
so it has very limited browser support.最大的缺点:它依赖于
Object.observe()
,因此它对浏览器的支持非常有限。 And it doesn't look like it'll be coming for Firefox or Edge anytime soon.而且它看起来不会很快出现在 Firefox 或 Edge 上。
Let's say you have the following array called movies: 假设您有一个称为电影的以下数组:
var movies = ["Reservoir Dogs", "Pulp Fiction", "Jackie Brown",
"Kill Bill", "Death Proof", "Inglourious Basterds"];
Using the stringify function, your movies array can be turned into a string by using the following syntax: 使用字符串化功能,可以使用以下语法将电影数组转换为字符串:
localStorage.setItem("quentinTarantino", JSON.stringify(movies));
Notice that my data is being stored under the key called quentinTarantino. 请注意,我的数据存储在名为quentinTarantino的密钥下。
Retrieving Your Data 检索数据
var retrievedData = localStorage.getItem("quentinTarantino");
To convert from a string back to an object, use the JSON parse function: 要将字符串从字符串转换回对象,请使用JSON解析函数:
var movies2 = JSON.parse(retrievedData);
You can call all of the array methods on your movies2 您可以在电影上调用所有数组方法2
I found a way to make it work with objects that have cyclic references.我找到了一种使它与具有循环引用的对象一起工作的方法。
Let's make an object with cyclic references.让我们用循环引用创建一个对象。
obj = {
L: {
L: { v: 'lorem' },
R: { v: 'ipsum' }
},
R: {
L: { v: 'dolor' },
R: {
L: { v: 'sit' },
R: { v: 'amet' }
}
}
}
obj.R.L.uncle = obj.L;
obj.R.R.uncle = obj.L;
obj.R.R.L.uncle = obj.R.L;
obj.R.R.R.uncle = obj.R.L;
obj.L.L.uncle = obj.R;
obj.L.R.uncle = obj.R;
We can't do JSON.stringify
here, because of the circular references.由于循环引用,我们不能在这里做
JSON.stringify
。
LOCALSTORAGE.CYCLICJSON
has .stringify
and .parse
just like normal JSON
, but works with objects with circular references. LOCALSTORAGE.CYCLICJSON
具有.stringify
和.parse
就像普通的JSON
一样,但适用于具有循环引用的对象。 ("Works" meaning parse(stringify(obj)) and obj are deep equal AND have identical sets of 'inner equalities') (“Works”意味着 parse(stringify(obj)) 和 obj 是深度相等的,并且具有相同的“内部相等”集)
But we can just use the shortcuts:但我们可以只使用快捷方式:
LOCALSTORAGE.setObject('latinUncles', obj)
recovered = LOCALSTORAGE.getObject('latinUncles')
Then, recovered
will be "the same" to obj, in the following sense:那么,
recovered
将与 obj “相同”,在以下意义上:
[
obj.L.L.v === recovered.L.L.v,
obj.L.R.v === recovered.L.R.v,
obj.R.L.v === recovered.R.L.v,
obj.R.R.L.v === recovered.R.R.L.v,
obj.R.R.R.v === recovered.R.R.R.v,
obj.R.L.uncle === obj.L,
obj.R.R.uncle === obj.L,
obj.R.R.L.uncle === obj.R.L,
obj.R.R.R.uncle === obj.R.L,
obj.L.L.uncle === obj.R,
obj.L.R.uncle === obj.R,
recovered.R.L.uncle === recovered.L,
recovered.R.R.uncle === recovered.L,
recovered.R.R.L.uncle === recovered.R.L,
recovered.R.R.R.uncle === recovered.R.L,
recovered.L.L.uncle === recovered.R,
recovered.L.R.uncle === recovered.R
]
Here is the implementation of LOCALSTORAGE
这是
LOCALSTORAGE
的实现
LOCALSTORAGE = (function(){ "use strict"; var ignore = [Boolean, Date, Number, RegExp, String]; function primitive(item){ if (typeof item === 'object'){ if (item === null) { return true; } for (var i=0; i<ignore.length; i++){ if (item instanceof ignore[i]) { return true; } } return false; } else { return true; } } function infant(value){ return Array.isArray(value) ? [] : {}; } function decycleIntoForest(object, replacer) { if (typeof replacer !== 'function'){ replacer = function(x){ return x; } } object = replacer(object); if (primitive(object)) return object; var objects = [object]; var forest = [infant(object)]; var bucket = new WeakMap(); // bucket = inverse of objects bucket.set(object, 0); function addToBucket(obj){ var result = objects.length; objects.push(obj); bucket.set(obj, result); return result; } function isInBucket(obj){ return bucket.has(obj); } function processNode(source, target){ Object.keys(source).forEach(function(key){ var value = replacer(source[key]); if (primitive(value)){ target[key] = {value: value}; } else { var ptr; if (isInBucket(value)){ ptr = bucket.get(value); } else { ptr = addToBucket(value); var newTree = infant(value); forest.push(newTree); processNode(value, newTree); } target[key] = {pointer: ptr}; } }); } processNode(object, forest[0]); return forest; }; function deForestIntoCycle(forest) { var objects = []; var objectRequested = []; var todo = []; function processTree(idx) { if (idx in objects) return objects[idx]; if (objectRequested[idx]) return null; objectRequested[idx] = true; var tree = forest[idx]; var node = Array.isArray(tree) ? [] : {}; for (var key in tree) { var o = tree[key]; if ('pointer' in o) { var ptr = o.pointer; var value = processTree(ptr); if (value === null) { todo.push({ node: node, key: key, idx: ptr }); } else { node[key] = value; } } else { if ('value' in o) { node[key] = o.value; } else { throw new Error('unexpected') } } } objects[idx] = node; return node; } var result = processTree(0); for (var i = 0; i < todo.length; i++) { var item = todo[i]; item.node[item.key] = objects[item.idx]; } return result; }; var console = { log: function(x){ var the = document.getElementById('the'); the.textContent = the.textContent + '\n' + x; }, delimiter: function(){ var the = document.getElementById('the'); the.textContent = the.textContent + '\n*******************************************'; } } function logCyclicObjectToConsole(root) { var cycleFree = decycleIntoForest(root); var shown = cycleFree.map(function(tree, idx) { return false; }); var indentIncrement = 4; function showItem(nodeSlot, indent, label) { var leadingSpaces = ' '.repeat(indent); var leadingSpacesPlus = ' '.repeat(indent + indentIncrement); if (shown[nodeSlot]) { console.log(leadingSpaces + label + ' ... see above (object #' + nodeSlot + ')'); } else { console.log(leadingSpaces + label + ' object#' + nodeSlot); var tree = cycleFree[nodeSlot]; shown[nodeSlot] = true; Object.keys(tree).forEach(function(key) { var entry = tree[key]; if ('value' in entry) { console.log(leadingSpacesPlus + key + ": " + entry.value); } else { if ('pointer' in entry) { showItem(entry.pointer, indent + indentIncrement, key); } } }); } } console.delimiter(); showItem(0, 0, 'root'); }; function stringify(obj){ return JSON.stringify(decycleIntoForest(obj)); } function parse(str){ return deForestIntoCycle(JSON.parse(str)); } var CYCLICJSON = { decycleIntoForest: decycleIntoForest, deForestIntoCycle : deForestIntoCycle, logCyclicObjectToConsole: logCyclicObjectToConsole, stringify : stringify, parse : parse } function setObject(name, object){ var str = stringify(object); localStorage.setItem(name, str); } function getObject(name){ var str = localStorage.getItem(name); if (str===null) return null; return parse(str); } return { CYCLICJSON : CYCLICJSON, setObject : setObject, getObject : getObject } })(); obj = { L: { L: { v: 'lorem' }, R: { v: 'ipsum' } }, R: { L: { v: 'dolor' }, R: { L: { v: 'sit' }, R: { v: 'amet' } } } } obj.RLuncle = obj.L; obj.RRuncle = obj.L; obj.RRLuncle = obj.RL; obj.RRRuncle = obj.RL; obj.LLuncle = obj.R; obj.LRuncle = obj.R; // LOCALSTORAGE.setObject('latinUncles', obj) // recovered = LOCALSTORAGE.getObject('latinUncles') // localStorage not available inside fiddle ): LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(obj) putIntoLS = LOCALSTORAGE.CYCLICJSON.stringify(obj); recovered = LOCALSTORAGE.CYCLICJSON.parse(putIntoLS); LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(recovered); var the = document.getElementById('the'); the.textContent = the.textContent + '\n\n' + JSON.stringify( [ obj.LLv === recovered.LLv, obj.LRv === recovered.LRv, obj.RLv === recovered.RLv, obj.RRLv === recovered.RRLv, obj.RRRv === recovered.RRRv, obj.RLuncle === obj.L, obj.RRuncle === obj.L, obj.RRLuncle === obj.RL, obj.RRRuncle === obj.RL, obj.LLuncle === obj.R, obj.LRuncle === obj.R, recovered.RLuncle === recovered.L, recovered.RRuncle === recovered.L, recovered.RRLuncle === recovered.RL, recovered.RRRuncle === recovered.RL, recovered.LLuncle === recovered.R, recovered.LRuncle === recovered.R ] )
<pre id='the'></pre>
This question has been answered sufficiently from the JavaScript-only perspective, and others have already noted that both localStorage.getItem
and localStorage.setItem
have no concept of objects—they handle strings and strings only.这个问题已经从纯 JavaScript 的角度得到了充分的回答,其他人已经注意到
localStorage.getItem
和localStorage.setItem
都没有对象的概念——它们只处理字符串和字符串。 This answer provides a TypeScript-friendly solution that incorporates what others have suggested in JavaScript-only solutions.这个答案提供了一个 TypeScript 友好的解决方案,它结合了其他人在纯 JavaScript 解决方案中的建议。
Storage.prototype.setObject = function (key: string, value: unknown) {
this.setItem(key, JSON.stringify(value));
};
Storage.prototype.getObject = function (key: string) {
const value = this.getItem(key);
if (!value) {
return null;
}
return JSON.parse(value);
};
declare global {
interface Storage {
setObject: (key: string, value: unknown) => void;
getObject: (key: string) => unknown;
}
}
localStorage.setObject('ages', [23, 18, 33, 22, 58]);
localStorage.getObject('ages');
We declare both setObject
and getObject
functions on the Storage
prototype— localStorage
is an instance of this type.我们在
Storage
原型上声明了setObject
和getObject
函数localStorage
就是这种类型的一个实例。 There's nothing special we really need to note besides the null handling in getObject
.除了
getObject
中的 null 处理之外,没有什么特别需要注意的。 Since getItem
can return null
, we must exit early since calling JSON.parse
on a null
value will throw a runtime exception.由于
getItem
可以返回null
,我们必须提前退出,因为对null
值调用JSON.parse
会引发运行时异常。
After declaring the functions on the Storage
prototype, we include their type definitions on the Storage
type in the global namespace.在
Storage
原型上声明函数后,我们将它们的类型定义包含在全局命名空间中的Storage
类型上。
Note: If we defined these functions with arrow functions, we'd need to assume that the storage object we're calling is always localStorage
, which might not be true.注意:如果我们用箭头函数定义这些函数,我们需要假设我们调用的存储对象总是
localStorage
,这可能不是真的。 For instance, the above code will add setObject
and getObject
support to sessionStorage
as well.例如,上面的代码也会为
sessionStorage
添加setObject
和getObject
支持。
I'd like to store a JavaScript object in HTML5 localStorage
, but my object is apparently being converted to a string.我想将JavaScript对象存储在HTML5
localStorage
,但是我的对象显然正在转换为字符串。
I can store and retrieve primitive JavaScript types and arrays using localStorage
, but objects don't seem to work.我可以使用
localStorage
存储和检索原始JavaScript类型和数组,但是对象似乎无法正常工作。 Should they?应该吗
Here's my code:这是我的代码:
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);
The console output is控制台输出为
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
It looks to me like the setItem
method is converting the input to a string before storing it.在我看来,
setItem
方法在存储输入之前将输入转换为字符串。
I see this behavior in Safari, Chrome, and Firefox, so I assume it's my misunderstanding of the HTML5 Web Storage spec, not a browser-specific bug or limitation.我在Safari,Chrome和Firefox中看到了这种现象,因此我认为这是我对HTML5 Web存储规范的误解,而不是浏览器特定的错误或限制。
I've tried to make sense of the structured clone algorithm described in http://www.w3.org/TR/html5/infrastructure.html .我试图弄清http://www.w3.org/TR/html5/infrastructure.html中描述的结构化克隆算法。 I don't fully understand what it's saying, but maybe my problem has to do with my object's properties not being enumerable (???)
我不完全理解这是什么意思,但是也许我的问题与我的对象的属性不可枚举有关(???)
Is there an easy workaround?有一个简单的解决方法吗?
Update: The W3C eventually changed their minds about the structured-clone specification, and decided to change the spec to match the implementations.更新:W3C最终改变了对结构化克隆规范的想法,并决定更改规范以匹配实现。 See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 .
参见https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 。 So this question is no longer 100% valid, but the answers still may be of interest.
因此,此问题不再100%有效,但答案可能仍然很有趣。
Localstorage can only store key-value pairs where both of the keys and the values have to be strings . Localstorage只能存储键和值都必须为string的键-值对。 However, you can store object by serializing them to
JSON
strings and then deserialize them to JS objects when you retrieve them. 但是,您可以通过将对象序列化为
JSON
字符串,然后在检索它们时将它们反序列化为JS对象来存储对象。
For example: 例如:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
// JSON.stringify turns a JS object into a JSON string, thus we can store it
localStorage.setItem('testObject', JSON.stringify(testObject));
// After we recieve a JSON string we can parse it into a JS object using JSON.parse
var jsObject = JSON.parse(localStorage.getItem('testObject'));
Be aware of the fact that this will remove the established prototype chain. 请注意,这将删除已建立的原型链。 This is best shown via an example:
最好通过示例显示:
function testObject () { this.one = 1; this.two = 2; this.three = 3; } testObject.prototype.hi = 'hi'; var testObject1 = new testObject(); // logs the string hi, derived from prototype console.log(testObject1.hi); // the prototype of testObject1 is testObject.prototype console.log(Object.getPrototypeOf(testObject1)); // stringify and parse the js object, will result in a normal JS object var parsedObject = JSON.parse(JSON.stringify(testObject1)); // the newly created object now has Object.prototype as its prototype console.log(Object.getPrototypeOf(parsedObject) === Object.prototype); // no longer is testObject the prototype console.log(Object.getPrototypeOf(parsedObject) === testObject.prototype); // thus we cannot longer access the hi property since this was on the prototype console.log(parsedObject.hi); // undefined
I have this JS Object * I want to store this in HTML5 Local storage 我有这个JS对象 *我想将其存储在HTML5本地存储中
todosList = [
{ id: 0, text: "My todo", finished: false },
{ id: 1, text: "My first todo", finished: false },
{ id: 2, text: "My second todo", finished: false },
{ id: 3, text: "My third todo", finished: false },
{ id: 4, text: "My 4 todo", finished: false },
{ id: 5, text: "My 5 todo", finished: false },
{ id: 6, text: "My 6 todo", finished: false },
{ id: 7, text: "My 7 todo", finished: false },
{ id: 8, text: "My 8 todo", finished: false },
{ id: 9, text: "My 9 todo", finished: false }
];
I can store this in HTML5 Local storage in this way, by using JSON.stringify 我可以在HTML5本地存储以这种方式, 存储这个由透过JSON.stringify
localStorage.setItem("todosObject", JSON.stringify(todosList));
And Now i can get this Object from Local storage by JSON.parsing . 现在,我可以通过JSON.parsing从本地存储获取此对象。
todosList1 = JSON.parse(localStorage.getItem("todosObject"));
console.log(todosList1);
In this answer I focus on data-only objects (without functions, etc.) with circular references and develop ideas mentioned by maja and mathheadinclouds (I use his test case and my code is several times shorter).在这个答案中,我专注于具有循环引用的纯数据对象(没有函数等),并开发了 maja和 mathheadinclouds提到的想法(我使用他的测试用例,我的代码要短几倍)。
Actually, we can use JSON.stringify with a proper replacer - if the source object contains multi-references to some object, or contains circular references then we reference it by special path-string (similar to JSONPath ).实际上,我们可以使用带有适当替换器的JSON.stringify - 如果源对象包含对某个对象的多重引用,或者包含循环引用,那么我们通过特殊的路径字符串(类似于JSONPath )引用它。
// JSON.strigify replacer for objects with circ ref function refReplacer() { let m = new Map(), v = new Map(), init = null; return function(field, value) { let p = m.get(this) + (Array.isArray(this) ? `[${field}]` : '.' + field); let isComplex = value === Object(value) if (isComplex) m.set(value, p); let pp = v.get(value)||''; let path = p.replace(/undefined\.\.?/, ''); let val = pp ? `#REF:${pp[0] == '[' ? '$':'$.'}${pp}` : value; !init ? (init=value) : (val===init ? val="#REF:$" : 0); if(!pp && isComplex) v.set(value, path); return val; } } // --------------- // TEST // --------------- // Generate obj with duplicate/circular references let obj = { L: { L: { v: 'lorem' }, R: { v: 'ipsum' } }, R: { L: { v: 'dolor' }, R: { L: { v: 'sit' }, R: { v: 'amet' } } } } obj.RLuncle = obj.L; obj.RRuncle = obj.L; obj.RRLuncle = obj.RL; obj.RRRuncle = obj.RL; obj.LLuncle = obj.R; obj.LRuncle = obj.R; testObject = obj; let json = JSON.stringify(testObject, refReplacer(), 4); console.log("Test Object\n", testObject); console.log("JSON with JSONpath references\n", json);
Parse such JSON content with JSONpath-like references:使用类似 JSONpath 的引用解析此类 JSON 内容:
// Parse JSON content with JSONpath references to object function parseRefJSON(json) { let objToPath = new Map(); let pathToObj = new Map(); let o = JSON.parse(json); let traverse = (parent, field) => { let obj = parent; let path = '#REF:$'; if (field !== undefined) { obj = parent[field]; path = objToPath.get(parent) + (Array.isArray(parent) ? `[${field}]` : `${field ? '.' + field : ''}`); } objToPath.set(obj, path); pathToObj.set(path, obj); let ref = pathToObj.get(obj); if (ref) parent[field] = ref; for (let f in obj) if (obj === Object(obj)) traverse(obj, f); } traverse(o); return o; } // --------------- // TEST 1 // --------------- let json = ` { "L": { "L": { "v": "lorem", "uncle": { "L": { "v": "dolor", "uncle": "#REF:$.L" }, "R": { "L": { "v": "sit", "uncle": "#REF:$.LLuncle.L" }, "R": { "v": "amet", "uncle": "#REF:$.LLuncle.L" }, "uncle": "#REF:$.L" } } }, "R": { "v": "ipsum", "uncle": "#REF:$.LLuncle" } }, "R": "#REF:$.LLuncle" }`; let testObject = parseRefJSON(json); console.log("Test Object\n", testObject); // --------------- // TEST 2 // --------------- console.log('Tests from mathheadinclouds answer: '); let recovered = testObject; let obj = { // Original object L: { L: { v: 'lorem' }, R: { v: 'ipsum' } }, R: { L: { v: 'dolor' }, R: { L: { v: 'sit' }, R: { v: 'amet' } } } } obj.RLuncle = obj.L; obj.RRuncle = obj.L; obj.RRLuncle = obj.RL; obj.RRRuncle = obj.RL; obj.LLuncle = obj.R; obj.LRuncle = obj.R; [ obj.LLv === recovered.LLv, obj.LRv === recovered.LRv, obj.RLv === recovered.RLv, obj.RRLv === recovered.RRLv, obj.RRRv === recovered.RRRv, obj.RLuncle === obj.L, obj.RRuncle === obj.L, obj.RRLuncle === obj.RL, obj.RRRuncle === obj.RL, obj.LLuncle === obj.R, obj.LRuncle === obj.R, recovered.RLuncle === recovered.L, recovered.RRuncle === recovered.L, recovered.RRLuncle === recovered.RL, recovered.RRRuncle === recovered.RL, recovered.LLuncle === recovered.R, recovered.LRuncle === recovered.R ].forEach(x => console.log('test pass: ' + x));
To load/save the resulting JSON content into storage, use the following code:要将生成的 JSON 内容加载/保存到存储中,请使用以下代码:
localStorage.myObject = JSON.stringify(testObject, refReplacer()); // Save
testObject = parseRefJSON(localStorage.myObject); // Load
I suggest using Jackson-js .我建议使用Jackson-js 。 It is a library that handles serializing and deserializing of Objects while retaining their structure, based on decorators.
它是一个基于装饰器处理对象的序列化和反序列化同时保留其结构的库。
The library handles all the pitfalls such as cyclic reference, attributes aliasing, etc.该库处理所有缺陷,例如循环引用、属性别名等。
Simply describe your class using the @JsonProperty() and @JsonClassType() decorators.使用 @JsonProperty() 和 @JsonClassType() 装饰器简单地描述你的类。
Serialize your object using:使用以下方法序列化您的对象:
const objectMapper = new ObjectMapper();
localstore.setItem(key, objectMapper.stringify<yourObjectType>(yourObject));
For slightly more detailed explanation, check my answer here:如需更详细的解释,请在此处查看我的答案:
Typescript objects serialization? 打字稿对象序列化?
And the Jackson-js tutorial here: Jackson-js 教程在这里:
Jackson-js: Powerful JavaScript decorators to serialize/deserialize objects into JSON and vice versa (Part 1) Jackson-js:强大的 JavaScript 装饰器,可将对象序列化/反序列化为 JSON,反之亦然(第 1 部分)
Looking from the answers it seems there are many ways to store a JavaScript object. 从答案看,似乎有很多方法可以存储JavaScript对象。
You may set Keyword: store
, Language: javascript
, sort by: 'Most Star'
您可以设置关键字:
store
,语言: javascript
,排序方式: 'Most Star'
Try this GitHub Link then you will get the current most choice on the top. 尝试使用此GitHub链接,您将在顶部获得当前最多的选择。
localStorage.setItem('user', JSON.stringify(user));
Then to retrieve it from the store and convert to an object again:然后从存储中检索它并再次转换为对象:
var user = JSON.parse(localStorage.getItem('user'));
If we need to delete all entries of the store we can simply do:
localStorage.clear();
Loop throught localstorage 遍历本地存储
var retrievedData = localStorage.getItem("MyCart");
retrievedData.forEach(function (item) {
console.log(item.itemid);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.