O localStorage.getItem (‘item’) é melhor que localStorage.item ou localStorage ?

Recentemente, fiz uma pergunta sobre o LocalStorage . O uso de JSON.parse(localStorage.item) e JSON.parse(localStorage['item']) não estava funcionando para retornar NULL quando o item ainda não havia sido definido.

No entanto, JSON.parse(localStorage.getItem('item') funcionou. E acontece, JSON.parse(localStorage.testObject || null) também funciona.

Um dos comentários basicamente dizia que localStorage.getItem() e localStorage.setItem() deveriam ser sempre preferidos:

O getter e o setter fornecem uma maneira consistente, padronizada e compatível com o navegador para trabalhar com a API LS e devem sempre ser preferidos em relação às outras formas. – Christoph

Eu comecei a gostar de usar as annotations de ponto abreviado e de colchetes para localStorage, mas estou curioso para saber que os outros assumem isso. LocalStorage.getItem (‘item’) é melhor que localStorage.item ou localStorage [‘item’] OU enquanto funcionarem são as notações abreviadas, ok?

O access direto à propriedade ( localStorage.item ou localStorage['item'] ) e o uso da interface funcional ( getItem('item') ) funcionam bem. Ambos são compatíveis com o padrão e entre navegadores. * De acordo com as especificações :

Os nomes das propriedades suportadas em um object Storage são as chaves de cada par chave / valor atualmente presente na lista associada ao object, na ordem em que as chaves foram adicionadas pela última vez à área de armazenamento.

Eles apenas se comportam de maneira diferente quando nenhum par de chave / valor é encontrado com o nome solicitado. Por exemplo, se a chave 'item' não existir, var a = localStorage.item; resultará em a undefined , enquanto var a = localStorage.getItem('item'); resultará em a valor null . Como você descobriu, undefined e null não são intercambiáveis ​​em JavaScript / EcmaScript. 🙂

EDIT: Como Christoph aponta em sua resposta , a interface funcional é a única maneira confiável para armazenar e recuperar valores em chaves iguais às propriedades predefinidas de localStorage ( length , key , setItem , getItem , removeItem e clear ). Então, por exemplo, o seguinte sempre funcionará:

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

Observe, em particular, que a primeira instrução não afetará a propriedade localStorage.length (exceto, talvez, incrementando-a, se já não houver nenhuma chave 'length' no localStorage ). Nesse aspecto, a especificação parece ser internamente inconsistente.

No entanto, o seguinte provavelmente não fará o que você deseja:

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

Curiosamente, o primeiro é um no-op no Chrome, mas é sinônimo da chamada funcional no Firefox. O segundo sempre registrará o número de chaves presentes no localStorage .

* Isso é verdade para navegadores que suportam armazenamento na Web, em primeiro lugar. (Isso inclui praticamente todos os navegadores de desktop e móveis modernos.) Para ambientes que simulam o armazenamento local usando cookies ou outras técnicas, o comportamento depende do calço usado. Vários polyfills para localStorage podem ser encontrados aqui .

A questão já é bastante antiga, mas desde que fui citado na pergunta, acho que devo dizer duas palavras sobre a minha declaração.

O object de armazenamento é bastante especial, é um object que fornece access a uma lista de pares chave / valor. Portanto, não é um object ou array comum.

Por exemplo, ele possui o atributo length, que, diferentemente do atributo length da matriz, é somente leitura e retorna o número de chaves no armazenamento.

Com um array você pode fazer:

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

Aqui temos o primeiro motivo para usar os getters / setters. E se você quiser definir um item chamado 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" 

Com outros membros do object Storage, é ainda mais crítico, pois eles são graváveis ​​e você pode sobrescrever acidentalmente methods como getItem . O uso dos methods da API evita qualquer um desses possíveis problemas e fornece uma interface consistente.

Outro ponto interessante é o seguinte parágrafo na especificação (enfatizada por mim):

Os methods setItem () e removeItem () devem ser atômicos em relação à falha. No caso de falha, o método não faz nada. Ou seja, as alterações na área de armazenamento de dados devem ser bem-sucedidas ou a área de armazenamento de dados não deve ser alterada.

Teoricamente, não deve haver diferença entre os getters / setters e o access [] , mas você nunca sabe …

Eu sei que é um post antigo, mas como ninguém mencionou o desempenho, configurei alguns testes JsPerf para fazer benchmark e, além de ser uma interface coerente, getItem e setItem também são consistentemente mais rápidos do que usar notação de ponto ou colchetes, além de serem muito mais fáceis de ler. .

Aqui estão meus testes no JsPerf

Como foi mencionado, quase não há diferença, exceto a chave inexistente. A diferença no desempenho varia dependendo de qual navegador / sistema operacional você está usando. Mas não é assim tão diferente.

Eu sugiro que você use interface padrão, apenas porque é uma maneira recomendada de usá-lo.