javascript - löschen - localstorage setitem




Speichern von Objekten in HTML5 localStorage (18)

Ich möchte ein JavaScript-Objekt in HTML5 localStorage , aber mein Objekt wird anscheinend in eine Zeichenfolge konvertiert.

Ich kann primitive JavaScript-Typen und localStorage mit localStorage speichern und abrufen, aber Objekte scheinen nicht zu funktionieren. Sollten Sie?

Hier ist mein 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);

Die Konsolenausgabe lautet

typeof testObject: object
testObject properties:
  one: 1
  two: 2
  three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]

Es sieht für mich so aus, als würde die setItem Methode die Eingabe vor dem Speichern in einen String konvertieren.

Ich sehe dieses Verhalten in Safari, Chrome und Firefox. Daher gehe ich davon aus, dass ich die HTML5-Web-Storage- Spezifikation nicht missverstanden habe, nicht einen browserspezifischen Fehler oder eine Einschränkung.

Ich habe versucht, den in http://www.w3.org/TR/html5/infrastructure.html beschriebenen strukturierten Klonalgorithmus zu verstehen. Ich verstehe nicht ganz, was es sagt, aber vielleicht hat mein Problem damit zu tun, dass die Eigenschaften meines Objekts nicht aufgezählt werden (???)

Gibt es eine einfache Problemumgehung?

Update: Das W3C änderte schließlich seine Meinung über die Spezifikation für strukturierte Klone und beschloss, die Spezifikation an die Implementierungen anzupassen. Siehe https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 . Diese Frage ist also nicht mehr zu 100% gültig, aber die Antworten könnten dennoch von Interesse sein.


Stringify löst nicht alle Probleme

Es scheint, dass die Antworten hier nicht alle Arten abdecken, die in JavaScript möglich sind, daher hier einige kurze Beispiele für den richtigen Umgang mit ihnen:

//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"

Ich empfehle das Speichern von Funktionen nicht, da eval() böse ist und zu Problemen in Bezug auf Sicherheit, Optimierung und Debugging führen kann. Im Allgemeinen sollte eval() niemals in JavaScript-Code verwendet werden.

Private Mitglieder

Das Problem bei der Verwendung von JSON.stringify() zum Speichern von Objekten besteht darin, dass diese Funktion private Member nicht serialisieren kann. Dieses Problem kann durch Überschreiben der .toString() -Methode (die beim Speichern von Daten im .toString() implizit .toString() gelöst werden:

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

Zirkelverweise

Ein weiteres Problem, mit dem stringify nicht umgehen kann, sind stringify :

var obj = {};
obj["circular"] = obj;
localStorage.object = JSON.stringify(obj);  //Fails

In diesem Beispiel JSON.stringify() einen TypeError "Konvertieren einer zirkularen Struktur in JSON" . Wenn das Speichern von JSON.stringify() unterstützt werden soll, kann der zweite Parameter von JSON.stringify() verwendet werden:

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

Die Suche nach einer effizienten Lösung zum Speichern von Zirkelreferenzen hängt jedoch in hohem Maße von den Aufgaben ab, die gelöst werden müssen. Auch das Wiederherstellen solcher Daten ist nicht trivial.

Es gibt bereits einige Fragen zu SO, die sich mit diesem Problem befassen : Stringify (in JSON konvertieren) ein JavaScript-Objekt mit Zirkelreferenz


Bei der Apple , Mozilla und Microsoft Dokumentation scheint die Funktionalität auf die Verarbeitung von nur String-Wert-Paaren beschränkt zu sein.

Eine stringify kann darin stringify das Objekt vor dem Speichern zu stringify und später beim Abrufen zu analysieren:

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

Das Erweitern des Speicherobjekts ist eine großartige Lösung. Für meine API habe ich eine Fassade für localStorage erstellt und dann beim Einstellen und Abrufen geprüft, ob es sich um ein Objekt handelt oder nicht.

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

Eine andere Option wäre die Verwendung eines vorhandenen Plugins.

Zum Beispiel ist persisto ein Open Source-Projekt, das eine einfache Schnittstelle zu localStorage / sessionStorage bietet und die Persistenz für Formularfelder (Eingabe, Optionsfelder und Kontrollkästchen) automatisiert.

(Haftungsausschluss: Ich bin der Autor.)


Es gibt eine großartige Bibliothek, die viele Lösungen jStorage so dass sogar ältere Browser mit dem Namen jStorage

Sie können ein Objekt festlegen

$.jStorage.set(key, value)

Und einfach abrufen

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

Es kann nützlich sein, das Speicherobjekt mit diesen praktischen Methoden zu erweitern:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

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

Auf diese Weise erhalten Sie die Funktionalität, die Sie wirklich wollten, obwohl unterhalb der API nur Zeichenfolgen unterstützt werden.


Hier einige erweiterte Version des von @danott geposteten Codes

Außerdem wird ein Löschwert aus localstorage implementiert und es wird gezeigt, wie anstelle von eine Getter- und Setter-Ebene hinzugefügt wird

localstorage.setItem(preview, true)

Du kannst schreiben

config.preview = true

Okay hier waren los:

var PT=Storage.prototype

if (typeof PT._setItem >='u') PT._setItem = PT.setItem;
PT.setItem = function(key, value)
{
  if (typeof value >='u')//..ndefined
    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')
//...

// Config Data transfer
//set
config.preview = true

//get
config.preview

// delete
config.preview = undefined

Nun, Sie können den Alias-Teil mit .bind(...) . Ich habe es jedoch nur eingefügt, da es wirklich gut ist, dies zu wissen. Ich brauchte Stunden, um herauszufinden, warum ein einfaches get = localStorage.getItem; arbeite nicht


Ich bin zu diesem Beitrag gekommen, nachdem ich einen anderen Beitrag angeschlagen habe, der als Duplikat dieses Artikels geschlossen wurde - mit dem Titel 'Wie speichert man ein Array in localstorage?'. Was in Ordnung ist, außer, dass keiner der Threads eine vollständige Antwort darauf gibt, wie Sie ein Array in localStorage verwalten können - es ist mir jedoch gelungen, eine Lösung basierend auf den in beiden Threads enthaltenen Informationen zu erstellen.

Wenn also jemand anderes in der Lage sein soll, Elemente innerhalb eines Arrays zu verschieben / zu platzieren / zu verschieben, und das Array in localStorage oder sogar in sessionStorage gespeichert werden soll, können Sie Folgendes tun:

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

Verwendungsbeispiel - Speichern von einfachen Zeichenfolgen im localStorage-Array:

localStorage.pushArrayItem('myArray','item one');
localStorage.pushArrayItem('myArray','item two');

Verwendungsbeispiel - Speichern von Objekten im sessionStorage-Array:

var item1 = {}; item1.name = 'fred'; item1.age = 48;
sessionStorage.pushArrayItem('myArray',item1);

var item2 = {}; item2.name = 'dave'; item2.age = 22;
sessionStorage.pushArrayItem('myArray',item2);

gängige Methoden zur Bearbeitung von 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

Ich habe einen weiteren minimalistischen Wrapper mit nur 20 Zeilen Code erstellt, um es wie folgt verwenden zu können:

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


Ich habe etwas erstellt, das die vorhandenen Speicherobjekte nicht zerstört, sondern einen Wrapper erstellt, damit Sie tun können, was Sie möchten. Das Ergebnis ist ein normales Objekt, keine Methoden, mit Zugriff wie jedes Objekt.

Was ich gemacht habe

Wenn Sie möchten, dass 1 localStorage Eigenschaft magisch ist:

var prop = ObjectStorage(localStorage, 'prop');

Wenn Sie mehrere benötigen:

var storage = ObjectStorage(localStorage, ['prop', 'more', 'props']);

Alles, was Sie tun, um zu prop , oder die Objekte im storage werden automatisch in localStorage . Du spielst immer mit einem echten Objekt, also kannst du so etwas tun:

storage.data.list.push('more data');
storage.another.list.splice(1, 2, {another: 'object'});

Jedes neue Objekt innerhalb eines verfolgten Objekts wird automatisch verfolgt.

Der große Nachteil: Es hängt von Object.observe() daher hat es eine sehr eingeschränkte Browserunterstützung. Und es sieht nicht so aus, als würde es in Kürze für Firefox oder Edge kommen.


Mit localDataStorage können localDataStorage Javascript-Datentypen (Array, Boolean, Date, Float, Integer, String und Object) transparent speichern. Es bietet auch eine einfache Datenverschleierung, komprimiert Zeichenketten automatisch, vereinfacht die Abfrage nach Schlüssel (Name) sowie die Abfrage nach (Schlüssel) -Wert und hilft, segmentierten, gemeinsam genutzten Speicher in derselben Domäne durch Präfix von Schlüsseln zu erzwingen.

[DISCLAIMER] Ich bin der Autor des Dienstprogramms [/ DISCLAIMER]

Beispiele:

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

Wie Sie sehen, werden die Grundwerte respektiert.


Sie können ejson , um die Objekte als Zeichenfolgen zu speichern.

EJSON ist eine Erweiterung von JSON, um weitere Typen zu unterstützen. Es unterstützt alle JSON-sicheren Typen sowie:

Alle EJSON-Serialisierungen sind ebenfalls gültige JSON. Ein Objekt mit einem Datum und einem binären Puffer würde beispielsweise in EJSON wie folgt serialisiert:

{
  "d": {"$date": 1358205756553},
  "b": {"$binary": "c3VyZS4="}
}

Hier ist mein localStorage-Wrapper mit Ejson

https://github.com/UziTech/storage.js

Ich habe meinem Wrapper einige Typen hinzugefügt, einschließlich regulärer Ausdrücke und Funktionen


Theoretisch können Objekte mit Funktionen gespeichert werden:

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

Die Serialisierung / Deserialisierung von Funktionen ist jedoch unzuverlässig, da sie implementierungsabhängig ist .


Verbesserung der Antwort von @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;
    }
};

http://rhaboo.org ist eine localStorage-Zuckerschicht, mit der Sie Folgendes schreiben können:

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

Es wird nicht JSON.stringify / parse verwendet, da dies bei großen Objekten ungenau und langsam wäre. Stattdessen hat jeder Terminalwert einen eigenen localStorage-Eintrag.

Sie können sich vermutlich vorstellen, dass ich etwas mit Rhaboo zu tun habe ;-)

Adrian


Sieh dir das an

Nehmen wir an, Sie haben das folgende Array mit dem Namen Movies:

var movies = ["Reservoir Dogs", "Pulp Fiction", "Jackie Brown", 
              "Kill Bill", "Death Proof", "Inglourious Basterds"];

Mit der Funktion "stringify" kann Ihr Film-Array mit der folgenden Syntax in eine Zeichenfolge umgewandelt werden:

localStorage.setItem("quentinTarantino", JSON.stringify(movies));

Beachten Sie, dass meine Daten unter dem Schlüssel quentinTarantino gespeichert werden.

Daten abrufen

var retrievedData = localStorage.getItem("quentinTarantino");

Verwenden Sie zur Konvertierung eines Strings in ein Objekt die JSON-Funktion parsen:

var movies2 = JSON.parse(retrievedData);

Sie können alle Array-Methoden in Ihren Filmen aufrufen2


Ich denke, um solche Probleme auf lokalen, Session-Cookies zu vermeiden, können Sie opendb-Bibliothek verwenden.

Beispiel: In diesem Abschnitt können Sie dieses Problem lösen

// for set object in db
db.local.setJSON("key", {name: "xyz"});  

// for get object form db
db.local.getJSON("key");

https://github.com/pankajbisht/openDB

Für weitere Informationen über Web - Speicher können Sie lesen Webspeicher Artikel.


Schleife durch den lokalen Speicher

var retrievedData = localStorage.getItem("MyCart");                 

retrievedData.forEach(function (item) {
   console.log(item.itemid);
});




local-storage