¿Es localStorage.getItem ('item') mejor que localStorage.item o localStorage ['item']?

84

Recientemente hice una pregunta sobre LocalStorage . Usando JSON.parse(localStorage.item)y JSON.parse(localStorage['item'])no estaban funcionando para regresar NULLcuando el artículo aún no se había configurado.

Sin embargo, JSON.parse(localStorage.getItem('item')funcionó. Y resulta que JSON.parse(localStorage.testObject || null)también funciona.

Uno de los comentarios básicamente decía que localStorage.getItem()y localStorage.setItem()siempre debería preferirse:

El getter y setter proporcionan una forma consistente, estandarizada y compatible con navegadores cruzados para trabajar con la API de LS y siempre deben preferirse a las otras formas. - Christoph

Me ha llegado a gustar el uso de las notaciones taquigráficas de puntos y corchetes para localStorage, pero tengo curiosidad por conocer la opinión de los demás sobre esto. ¿Es localStorage.getItem ('item') mejor que localStorage.item o localStorage ['item'] O mientras funcionen, las notaciones abreviadas están bien?

Mark Rummel
fuente
Creo que Christoph ha dejado bastante claro su razonamiento. getItemy setItemson la forma estandarizada de hacer las cosas.
Fabrício Matté
1
Veo. Un poco demasiado somnoliento para leer esas recomendaciones, pero como esta API de almacenamiento web es relativamente nueva, personalmente me quedo con los métodos getItem/ debidamente documentados setItem. Volveré a leer las especificaciones más tarde, pero la única forma infalible de responder a su pregunta es realizar pruebas en todos los navegadores principales.
Fabrício Matté
4
La especificación dice "Los nombres de propiedad admitidos en un objeto de almacenamiento son las claves de cada par clave / valor actualmente presente en la lista asociada con el objeto". ¿No hace eso localStorage.itemestandarizado también?
Barmar
2
@Barmar Una respuesta un poco tardía, pero después de ver tantos incautos de esta pregunta y volver aquí, responderé que tienes toda la razón. Sin embargo, recomendaré nuevamente usar getItem/ setItemporque estos métodos no entran en conflicto con las propiedades existentes del localStorageobjeto. Ejemplo: localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));funciona, mientras localStorage.getItem = 'blah';que sobrescribirá el getItemmétodo de localStorage . jsfiddle.net/DrquY
Fabrício Matté
1
Todavía no he visto un argumento a favor de ninguno de los enfoques que me convenció. Uno hace pares de nombre / valor como siempre lo ha sido. El otro nos da nulos cuando usamos métodos get / set. Supongo que si estuviera comparando con otra lista de valores que tuvieran nulos para los valores opcionales, uno tendría más sentido que el otro, pero decir que uno o el otro es 'preferido' cuando ambos están en la especificación es una tontería, en mi opinión. Ambos enfoques se pusieron a disposición por una razón.
Erik Reppen

Respuestas:

83

Tanto el acceso directo a la propiedad ( localStorage.itemo localStorage['item']) como el uso de la interfaz funcional ( localStorage.getItem('item')) funcionan bien. Ambos son estándar y compatibles con varios navegadores. * Según la especificación :

Los nombres de propiedad admitidos en un objeto de almacenamiento son las claves de cada par clave / valor actualmente presente en la lista asociada con el objeto, en el orden en que las claves se agregaron por última vez al área de almacenamiento.

Simplemente se comportan de manera diferente cuando no se encuentra un par clave / valor con el nombre solicitado. Por ejemplo, si la clave 'item'no existe, var a = localStorage.item;resultará en aser undefined, mientras var a = localStorage.getItem('item');que resultará en atener el valor null. Como usted ha descubierto, undefinedy nullno son intercambiables en JavaScript / EcmaScript. :)

EDITAR: Como Christoph señala en su respuesta , la interfaz funcional es la única forma de almacenar y recuperar de manera confiable valores bajo claves iguales a las propiedades predefinidas de localStorage. (Hay seis de ellos: length, key, setItem, getItem, removeItem, y clear.) Así, por ejemplo, lo siguiente será siempre el trabajo:

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

Nota en particular que la primera declaración no afectará a la propiedad localStorage.length(excepto, quizás, incrementándolo si no había llave 'length'ya localStorage). En este sentido, la especificación parece ser internamente inconsistente.

Sin embargo, lo siguiente probablemente no hará lo que desea:

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

Curiosamente, el primero es un no-op en Chrome, pero es sinónimo de la llamada funcional en Firefox. El segundo siempre registrará el número de claves presentes localStorage.

* Esto es cierto para los navegadores que admiten el almacenamiento web en primer lugar. (Esto incluye prácticamente todos los navegadores de escritorio y móviles modernos). Para entornos que simulan el almacenamiento local mediante cookies u otras técnicas, el comportamiento depende de la corrección que se utilice. AquílocalStorage se pueden encontrar varios polyfills para .

Ted Hopp
fuente
11

La pregunta ya es bastante antigua, pero dado que se me ha citado en la pregunta, creo que debería decir dos palabras sobre mi declaración.

El objeto de almacenamiento es bastante especial, es un objeto que proporciona acceso a una lista de pares clave / valor. Por lo tanto, no es un objeto o matriz ordinaria.

Por ejemplo, tiene el atributo de longitud, que a diferencia del atributo de longitud de la matriz, es de solo lectura y devuelve el número de claves en el almacenamiento.

Con una matriz puedes hacer:

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

Aquí tenemos la primera razón para usar getters / setters. ¿Qué sucede si desea configurar un elemento llamado 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 otros miembros del objeto Storage, es aún más crítico, ya que se pueden escribir en ellos y puede sobrescribir accidentalmente métodos como getItem. El uso de los métodos de la API evita cualquiera de estos posibles problemas y proporciona una interfaz coherente.

Otro punto interesante es el siguiente párrafo en la especificación (enfatizado por mí):

Los métodos setItem () y removeItem () deben ser atómicos con respecto a la falla. En caso de falla, el método no hace nada. Es decir, los cambios en el área de almacenamiento de datos deben tener éxito o el área de almacenamiento de datos no debe cambiarse en absoluto.

Teóricamente no debería haber diferencia entre los getters / setters y el []acceso, pero nunca se sabe ...

Christoph
fuente
En el primer punto, casi todo en JavaScript se puede escribir y la API localStorage solo tiene tres propiedades que conozco. En el segundo, al usar los enfoques de notación de puntos o corchetes, todavía está alcanzando algún tipo de implementación de establecedor nativo, ya que los valores se convierten automáticamente en cadenas sin importar cómo los establezca, por lo que debería tener las mismas salvaguardas disponibles. De hecho, nunca antes había oído hablar de un valor persistente que se corrompiera en un escenario de navegador del lado del cliente. Sospecho que incluso los accesos vanilla suelen tener algún tipo de protección.
Erik Reppen
El punto sobre la colisión de nombres es excelente. La lengthpropiedad no cambiará (al menos en Chrome y Firefox [*]) si llama localStorage.setItem("length", something);, pero puede recuperar somethingcon localStorage.getItem("length");. Curiosamente, la asignación localStorage.length = something;en Chrome no es una operación, pero en Firefox se almacenará somethingdebajo de la clave "length"(que luego solo puede recuperar usando la interfaz funcional). [*] En realidad, en Firefox, la lengthpropiedad cambiará si la clave aún "length"no está ingresada localStorage.
Ted Hopp
@ErikReppen - De acuerdo con la especificación , localStoragetiene seis propiedades predefinidas: length, key, getItem, setItem, removeItem, y clear.
Ted Hopp
1

Sé que es una entrada antigua, pero ya que nadie en realidad el rendimiento mencionado que creó algunas pruebas JsPerf establecer criterios de referencia y, además de ser una interfaz coherente getItemy setItemtambién son consistentemente más rápido que usando la notación de puntos o soportes, además de ser mucho más fácil de leer.

Aquí están mis pruebas en JsPerf

Dave Mackintosh
fuente
ur jsPerf no incluyó corchetes en su prueba. Los agregué y ejecuté algunas pruebas, el rendimiento se basa en el navegador. en Chrome y Firefox, getItemy setItemfueron los más lentos en cada categoría, siendo dot el más rápido en Chrome y el corchete más rápido en Firefox. También creo que 'ser mucho más fácil de leer' es completamente subjetivo ... sí, establece la función que está realizando, pero cualquiera que haya trabajado con variables de objeto o matriz sabría en medio segundo lo que está sucediendo con el punto / corchete.
PlantTheIdea
Tiene razón, en el momento de escribir esas pruebas, los captadores y definidores eran consistentemente más rápidos que la notación de puntos. Ya no es el caso. Cuando tenga 5 minutos, volveré y actualizaré esta respuesta. Gracias por señalar eso.
Dave Mackintosh
0

Como se mencionó, casi no hay diferencia excepto la clave inexistente. La diferencia en el rendimiento varía según el navegador / sistema operativo que esté utilizando. Pero en realidad no es tan diferente.

Le sugiero que use la interfaz estándar, solo porque es una forma recomendada de usarla.

Salvador Dalí
fuente
"Le sugiero que utilice la interfaz estándar" : ambas interfaces se especifican en el estándar.
Ted Hopp
@TedHopp Creo que solo setItem y getItem se especifican en el estándar .
Salvador Dali
2
De lo contrario. Del estándar: "Los nombres de propiedad admitidos en un objeto de almacenamiento son las claves de cada par clave / valor actualmente presente en la lista asociada con el objeto, en el orden en que las claves se agregaron por última vez al área de almacenamiento".
Ted Hopp