简体   繁体   English

HTML5 localStorage/sessionStorage中如何存储对象

[英]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.再次查看AppleMozillaMozilla文档,该功能似乎仅限于处理字符串键/值对。

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.这样,您可以实现自己的getset方法。 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;
  }
}

Stringify doesn't solve all problems Stringify 并不能解决所有问题

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 代码中使用。

Private members私人会员

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

Circular references循环引用

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

There is a great library that wraps many solutions so it even supports older browsers called jStorage有一个很棒的库包含许多解决方案,因此它甚至支持称为jStorage的旧浏览器

You can set an object你可以设置一个对象

$.jStorage.set(key, value)

And retrieve it easily并轻松检索

value = $.jStorage.get(key)
value = $.jStorage.get(key, "default value")

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 安全类型,以及:

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

Example usage : 示例用法

// 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.结果是一个普通对象,没有方法,可以像任何对象一样访问。

The thing I made.我做的东西。

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 .您对propstorage的对象所做的一切都会自动保存到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 上。

Look this 看看这个

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.getItemlocalStorage.setItem都没有对象的概念——它们只处理字符串和字符串。 This answer provides a TypeScript-friendly solution that incorporates what others have suggested in JavaScript-only solutions.这个答案提供了一个 TypeScript 友好的解决方案,它结合了其他人纯 JavaScript 解决方案中的建议

TypeScript 4.2.3打字稿 4.2.3

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;
  }
}

Usage用法

localStorage.setObject('ages', [23, 18, 33, 22, 58]);
localStorage.getObject('ages');

Explanation解释

We declare both setObject and getObject functions on the Storage prototype— localStorage is an instance of this type.我们在Storage原型上声明了setObjectgetObject函数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添加setObjectgetObject支持。

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

Circular References循环引用

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM