json.stringify non elabora i metodi dell’object

Sto cercando di sviluppare un’applicazione HTML5 offline che dovrebbe funzionare nella maggior parte dei browser moderni (Chrome, Firefox, IE 9+, Safari, Opera). Poiché IndexedDB non è supportato da Safari (ancora), e WebSQL è deprecato, ho deciso di utilizzare localStorage per archiviare gli oggetti JavaScript generati dagli utenti e JSON.stringify() / JSON.parse() per inserire o estrarre gli oggetti. Tuttavia, ho scoperto che JSON.stringify() non gestisce i metodi. Ecco un object di esempio con un metodo semplice:

  var myObject = {}; myObject.foo = 'bar'; myObject.someFunction = function () {/*code in this function*/} 

Se stringa questo object (e successivamente lo metto in localStorage), tutto ciò che verrà mantenuto è myObject.foo , non myObject.someFunction() .

  //put object into localStorage localStorage.setItem('myObject',JSON.stringify(myObject)); //pull it out of localStorage and set it to myObject myObject = localStorage.getItem('myObject'); //undefined! myObject.someFunction 

Sono sicuro che molti di voi probabilmente già conoscono questa limitazione / funzionalità / qualunque cosa si voglia chiamare. La soluzione alternativa che mi è venuta in mente è creare un object con i metodi ( myObject = new objectConstructor() ), estrarre le proprietà dell’object da localStorage e assegnarle al nuovo object che ho creato. Sento che questo è un approccio indiretto, ma sono nuovo nel mondo JavaScript, quindi è così che l’ho risolto. Quindi ecco la mia grande domanda: vorrei che l’intero object (proprietà + metodi) fosse incluso in localStorage. Come faccio a fare questo? Se puoi forse mostrarmi un algoritmo migliore, o forse un altro metodo JSON che non conosco, lo apprezzerei molto.

Le funzioni in javascript sono più di un semplice codice. Hanno anche scopo. Il codice può essere modificato, ma l’ambito non può.

JSON.stringify() codificherà i valori supportati da JSON. Oggetti con valori che possono essere oggetti, matrici, stringhe, numeri e valori booleani. Qualsiasi altra cosa sarà ignorata o causerà errori. Le funzioni non sono un’entity framework supportata in JSON. JSON gestisce solo i dati puri, le funzioni non sono dati, ma il comportamento con semantica più complessa.


Detto questo, puoi cambiare il modo in JSON.stringify() funziona JSON.stringify() . Il secondo argomento è una funzione di replacer . Quindi potresti forzare il comportamento che desideri forzando la strinigificazione delle funzioni:

 var obj = { foo: function() { return "I'm a function!"; } }; var json = JSON.stringify(obj, function(key, value) { if (typeof value === 'function') { return value.toString(); } else { return value; } }); console.log(json); // {"foo":"function () { return \"I'm a function!\" }"} 

Ma quando lo hai letto di nuovo, dovresti valutare la stringa di funzioni e riportare il risultato all’object, perché JSON non supporta le funzioni .


Tutto sumto, le funzioni di codifica in JSON possono diventare piuttosto pelose. Sei sicuro di volerlo fare? C’è probabilmente un modo migliore …

Forse potresti invece salvare i dati grezzi e passarli a un costruttore dal tuo JS caricato nella pagina. localStorage manterrà solo i dati, ma il tuo codice caricato nella pagina fornirà i metodi per operare su quei dati.

 // contrived example... var MyClass = function(data) { this.firstName = data.firstName; this.lastName = data.lastName; } MyClass.prototype.getName() { return this.firstName + ' ' + this.lastName; } localStorage.peopleData = [{ firstName: 'Bob', lastName: 'McDudeFace' }]; var peopleData = localStorage.peopleData; var bob = new MyClass(peopleData[0]); bob.getName() // 'Bob McDudeFace' 

Non è necessario salvare il metodo localStorage getName() su localStorage . Abbiamo solo bisogno di alimentare quei dati in un costruttore che fornirà quel metodo.

Se vuoi stringificare gli oggetti, ma hanno delle funzioni, puoi usare JSON.stringify() con il secondo replacer parametri. Per prevenire le dipendenze cicliche sugli oggetti, puoi usare var cache = [] .

Nel nostro progetto usiamo lodash . Usiamo la seguente funzione per generare registri. Può essere utilizzato per salvare oggetti su localStorage .

 var stringifyObj = function(obj) { var cache = [] return JSON.stringify(obj, function(key, value) { if ( _.isString(value) || _.isNumber(value) || _.isBoolean(value) ) { return value } else if (_.isError(value)) { return value.stack || '' } else if (_.isPlainObject(value) || _.isArray(value)) { if (cache.indexOf(value) !== -1) { return } else { // cache each item cache.push(value) return value } } }) } // create a circular object var circularObject = {} circularObject.circularObject = circularObject // stringify an object $('body').text( stringifyObj( { myBooblean: true, myString: 'foo', myNumber: 1, myArray: [1, 2, 3], myObject: {}, myCircularObject: circularObject, myFunction: function () {} } ) )