LocalStorage.getItem ('item') è migliore di localStorage.item o localStorage ['item']?


85

Di recente ho posto una domanda su LocalStorage . Usando JSON.parse(localStorage.item)e JSON.parse(localStorage['item'])non funzionavano per tornare NULLquando l'elemento non era stato ancora impostato.

Tuttavia, JSON.parse(localStorage.getItem('item')ha funzionato. E si scopre che JSON.parse(localStorage.testObject || null)funziona anche.

Uno dei commenti fondamentalmente lo diceva localStorage.getItem()e localStorage.setItem()dovrebbe essere sempre preferito:

Il getter e il setter forniscono un modo coerente, standardizzato e compatibile con il crossbrowser di lavorare con l'API LS e dovrebbero essere sempre preferiti rispetto agli altri modi. - Christoph

Mi è piaciuto usare le notazioni stenografiche punto e parentesi per localStorage, ma sono curioso di conoscere il punto di vista degli altri. LocalStorage.getItem ('item') è migliore di localStorage.item o localStorage ['item'] OPPURE finché funzionano le notazioni abbreviate vanno bene?


Credo che Christoph abbia reso il suo ragionamento abbastanza chiaro. getIteme setItemsono il modo standardizzato di fare le cose.
Fabrício Matté

1
Vedo. Un po 'troppo assonnato per sfogliare questi consigli, ma poiché questa API del webstorage è relativamente nuova, mi atterrei personalmente ai metodi getItem/ adeguatamente documentati setItem. Leggerò di nuovo le specifiche più tardi, ma l'unico modo a prova di errore per rispondere alla tua domanda è fare tutto il test su tutti i principali browser.
Fabrício Matté

4
La specifica dice "I nomi di proprietà supportati su un oggetto di archiviazione sono le chiavi di ogni coppia chiave / valore attualmente presente nell'elenco associato all'oggetto." Non è anche localStorage.itemstandardizzato?
Barmar

2
@Barmar Una risposta un po 'tardiva, ma dopo aver visto così tanti idioti di questa domanda e tornato qui, risponderò che hai assolutamente ragione. Tuttavia, ti consiglio di utilizzare nuovamente getItem/ setItemperché questi metodi non sono in conflitto con le proprietà esistenti localStoragedell'oggetto. Esempio: localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));funziona, mentre localStorage.getItem = 'blah';sovrascriverà il getItemmetodo di localStorage . jsfiddle.net/DrquY
Fabrício Matté

1
Non ho ancora visto un argomento a favore di entrambi gli approcci che mi ha conquistato. Si fanno coppie nome / valore come sono sempre state. L'altro ci dà valori nulli quando usiamo metodi get / set. Suppongo che se stessi confrontando con un altro elenco di valori che aveva null per i valori opzionali uno avrebbe più senso dell'altro, ma dire che l'uno o l'altro è "preferito" quando sono entrambi nella specifica è sciocco, IMO. Entrambi gli approcci sono stati resi disponibili per un motivo.
Erik Reppen

Risposte:


84

Sia l'accesso diretto alla proprietà ( localStorage.itemo localStorage['item']) che l'utilizzo dell'interfaccia funzionale ( localStorage.getItem('item')) funzionano bene. Entrambi sono compatibili standard e cross-browser. * Secondo le specifiche :

I nomi di proprietà supportati su un oggetto di archiviazione sono le chiavi di ciascuna coppia chiave / valore attualmente presente nell'elenco associato all'oggetto, nell'ordine in cui le chiavi sono state aggiunte l'ultima volta all'area di archiviazione.

Si comportano in modo diverso quando non viene trovata alcuna coppia chiave / valore con il nome richiesto. Ad esempio, se la chiave 'item'non esiste, var a = localStorage.item;risulterà in aessere undefined, mentre var a = localStorage.getItem('item');risulterà in aavere il valore null. Come hai scoperto undefinede nullnon sono intercambiabili in JavaScript / EcmaScript. :)

EDIT: come sottolinea Christoph nella sua risposta , l'interfaccia funzionale è l'unico modo per archiviare e recuperare in modo affidabile i valori sotto chiavi uguali alle proprietà predefinite di localStorage. (Ci sono sei di questi: length, key, setItem, getItem, removeItem, e clear.) Così, per esempio, il seguente funziona sempre:

localStorage.setItem('length', 2);
console.log(localStorage.getItem('length'));

Si noti in particolare che la prima istruzione non influenzerà la proprietà localStorage.length(tranne forse incrementandola se non c'era 'length'già una chiave localStorage). A questo proposito, le specifiche sembrano essere internamente incoerenti.

Tuttavia, probabilmente quanto segue non farà quello che vuoi:

localStorage.length = 2;
console.log(localStorage.length);

È interessante notare che il primo è un no-op in Chrome, ma è sinonimo di chiamata funzionale in Firefox. Il secondo registrerà sempre il numero di chiavi presentilocalStorage .

* Questo è vero per i browser che supportano l'archiviazione web in primo luogo. (Ciò include praticamente tutti i browser desktop e mobili moderni.) Per ambienti che simulano l'archiviazione locale utilizzando cookie o altre tecniche, il comportamento dipende dallo shim utilizzato. Diversi polyfill per localStoragepossono essere trovati qui .


12

La domanda è già piuttosto vecchia, ma poiché sono stata citata nella domanda, penso che dovrei dire due parole sulla mia affermazione.

L'oggetto di archiviazione è piuttosto speciale, è un oggetto che fornisce l'accesso a un elenco di coppie chiave / valore. Quindi non è un oggetto o un array ordinario.

Ad esempio, ha l'attributo length, che a differenza dell'attributo length dell'array è di sola lettura e restituisce il numero di chiavi nella memoria.

Con un array puoi fare:

var a = [1,2,3,4];
a.length // => 4
a.length = 2;
a // => [1,2]

Qui abbiamo il primo motivo per usare i getter / setter. E se volessi impostare un elemento chiamato length?

localStorage.length = "foo";
localStorage.length  // => 0
localStorage.setItem("length","foo");
// the "length" key is now only accessable via the getter method:
localStorage.length  // => 1
localStorage.getItem("length") // => "foo"

Con altri membri dell'oggetto Storage è ancora più critico, poiché sono scrivibili e puoi sovrascrivere accidentalmente metodi come getItem. L'utilizzo dei metodi API previene uno qualsiasi di questi possibili problemi e fornisce un'interfaccia coerente.

Un altro punto interessante è il seguente paragrafo nelle specifiche (sottolineato da me):

I metodi setItem () e removeItem () devono essere atomici rispetto al fallimento. In caso di fallimento, il metodo non fa nulla. Cioè, le modifiche all'area di archiviazione dei dati devono avere esito positivo oppure l'area di archiviazione dei dati non deve essere modificata affatto.

Teoricamente non dovrebbe esserci alcuna differenza tra i getter / setter e l' []accesso, ma non si sa mai ...


Sul primo punto, dannatamente quasi tutto in JavaScript è scrivibile e l'API localStorage ha solo tre proprietà di cui sono a conoscenza. Nel secondo, usando gli approcci di notazione punto o parentesi, stai ancora colpendo una sorta di implementazione del setter nativo poiché i valori vengono convertiti automaticamente in stringhe indipendentemente da come li imposti, quindi dovrebbe avere le stesse garanzie disponibili. In realtà non ho mai sentito parlare di un valore persistente che viene danneggiato in uno scenario di browser lato client prima. Sospetto che anche gli accessori vaniglia in genere abbiano una sorta di protezione.
Erik Reppen

Il punto sulla collisione dei nomi è eccellente. La lengthproprietà non cambierà (almeno in Chrome e Firefox [*]) se chiami localStorage.setItem("length", something);, ma puoi recuperare somethingcon localStorage.getItem("length");. È interessante notare che l'assegnazione localStorage.length = something;in Chrome non è un'operazione, ma in Firefox verrà memorizzata somethingsotto la chiave "length"(che puoi quindi recuperare solo utilizzando l'interfaccia funzionale). [*] In realtà, in Firefox, la lengthproprietà cambierà se la chiave "length"non è già presente localStorage.
Ted Hopp

@ErikReppen - Secondo le specifiche , localStorageha sei proprietà predefinite: length, key, getItem, setItem, removeItem, e clear.
Ted Hopp

1

So che è un vecchio post ma poiché nessuno ha effettivamente menzionato le prestazioni, ho impostato alcuni test JsPerf per confrontarlo e oltre ad essere un'interfaccia coerente getIteme setItemsono anche costantemente più veloci rispetto all'uso della notazione a punti o delle parentesi, oltre ad essere molto più facili da leggere.

Ecco i miei test su JsPerf


ur jsPerf non ha incluso le parentesi nel suo test. Li ho aggiunti ed eseguito alcuni test, le prestazioni sono basate su browser. sia su Chrome che su Firefox, getItemed setItemerano i più lenti in ogni categoria, con il punto che è più veloce su Chrome e la staffa che è più veloce su Firefox. Penso anche che 'essere molto più facile da leggere' sia del tutto soggettivo ... sì, afferma la funzione che sta eseguendo, ma chiunque abbia mai lavorato con variabili oggetto o array saprebbe in mezzo secondo cosa sta succedendo con punto / parentesi.
PlantTheIdea

Hai ragione, al momento della stesura di quei test i getter e i setter erano costantemente più veloci della notazione a punti. Non è più il caso. Quando avrò 5 minuti tornerò e aggiornerò questa risposta. Grazie per la segnalazione.
Dave Mackintosh

0

Come è stato detto, non c'è quasi nessuna differenza tranne che per la chiave inesistente. La differenza di prestazioni varia a seconda del browser / sistema operativo in uso. Ma non è poi così diverso.

Ti consiglio di usare l'interfaccia standard, solo perché è un modo consigliato di usarla.


"Ti suggerisco di utilizzare l'interfaccia standard" - Entrambe le interfacce sono specificate nello standard.
Ted Hopp

@TedHopp Penso che solo setItem e getItem siano specificati nello standard .
Salvador Dali

2
Anzi. Dallo standard: "I nomi di proprietà supportati su un oggetto di archiviazione sono le chiavi di ciascuna coppia chiave / valore attualmente presente nell'elenco associato all'oggetto, nell'ordine in cui le chiavi sono state aggiunte l'ultima volta all'area di archiviazione."
Ted Hopp
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.