Czy localStorage.getItem („item”) jest lepszy niż localStorage.item lub localStorage [„item”]?

84

Niedawno zadałem pytanie o LocalStorage . Używanie JSON.parse(localStorage.item)i JSON.parse(localStorage['item'])nie działało, aby powrócić, NULLgdy element nie został jeszcze ustawiony.

Jednak JSON.parse(localStorage.getItem('item')zadziałało. Okazuje się, że JSON.parse(localStorage.testObject || null)też działa.

Jeden z komentarzy zasadniczo to powiedział localStorage.getItem()i localStorage.setItem()zawsze powinien być preferowany:

Metody pobierające i ustawiające zapewniają spójny, ustandaryzowany i kompatybilny z różnymi przeglądarkami sposób pracy z interfejsem API LS i zawsze powinny być preferowane w stosunku do innych sposobów. - Christoph

Polubiłem używanie skróconych notacji z kropkami i nawiasami dla localStorage, ale jestem ciekawy, jak inni o tym myślą. Czy localStorage.getItem ('item') jest lepszy niż localStorage.item lub localStorage ['item'] LUB, o ile działają, czy zapisy skrótowe są w porządku?

Mark Rummel
źródło
Myślę, że Christoph przedstawił swoje rozumowanie całkiem jasno. getItemi setItemznormalizowanym sposobem działania.
Fabrício Matté,
1
Widzę. Trochę zbyt senny, by przejrzeć te zalecenia, ale ponieważ ten interfejs API do przechowywania w sieci Web jest stosunkowo nowy, osobiście trzymałbym się odpowiednio udokumentowanych getItem/ setItemmetod. Później ponownie przeczytam specyfikację, ale jedynym niezawodnym sposobem udzielenia odpowiedzi na pytanie jest wykonanie testów na wszystkich głównych przeglądarkach.
Fabrício Matté,
4
Specyfikacja mówi: „Obsługiwane nazwy właściwości w obiekcie pamięci masowej to klucze każdej pary klucz / wartość obecnie znajdującej się na liście skojarzonej z obiektem”. Czy to też nie czyni localStorage.itemstandaryzowanych?
Barmar
2
@Barmar Trochę spóźniona odpowiedź, ale po obejrzeniu tylu fałszywych odpowiedzi na to pytanie i powrocie tutaj, odpowiem, że masz całkowitą rację. Jednak zalecam ponowne użycie getItem/, setItemponieważ te metody nie powodują konfliktu z istniejącymi właściwościami localStorageobiektu. Przykład: localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));działa, while localStorage.getItem = 'blah';nadpisze getItemmetodę localStorage . jsfiddle.net/DrquY
Fabrício Matté
1
Nadal nie widziałem argumentu na rzecz któregokolwiek z podejść, które mnie przekonało. Tworzy się pary nazwa / wartość, jak zawsze. Drugi daje nam wartości null, gdy używamy metod get / set. Przypuszczam, że gdybym porównał z inną listą wartości, które miały wartość zerową dla wartości opcjonalnych, jedna z nich miałaby większy sens niż druga, ale stwierdzenie, że jedna lub druga jest „preferowana”, gdy obie są w specyfikacji, jest głupie, IMO. Oba podejścia zostały udostępnione z jakiegoś powodu.
Erik Reppen

Odpowiedzi:

84

Zarówno bezpośredni dostęp do właściwości ( localStorage.itemlub localStorage['item']), jak i użycie interfejsu funkcjonalnego ( localStorage.getItem('item')) działają dobrze. Oba są standardowe i kompatybilne z różnymi przeglądarkami. * Zgodnie ze specyfikacją :

Obsługiwane nazwy właściwości w obiekcie Storage to klucze każdej pary klucz / wartość aktualnie znajdującej się na liście skojarzonej z obiektem, w kolejności, w jakiej klucze zostały ostatnio dodane do obszaru przechowywania.

Po prostu zachowują się inaczej, gdy żadna para klucz / wartość nie zostanie znaleziona z żądaną nazwą. Na przykład, jeśli klucz 'item'nie istnieje, var a = localStorage.item;spowoduje to aistnienie undefined, a while var a = localStorage.getItem('item');będzie skutkować aposiadaniem wartości null. Jak odkryłeś , undefinedi nullnie są wymienne w JavaScript / EcmaScript. :)

EDYCJA: Jak wskazuje Christoph w swojej odpowiedzi , interfejs funkcjonalny jest jedynym sposobem niezawodnego przechowywania i pobierania wartości pod kluczami równymi wstępnie zdefiniowanym właściwościom localStorage. (Istnieje sześć z nich: length, key, setItem, getItem, removeItem, i clear.) Tak więc, na przykład, co następuje zawsze będzie działać:

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

Zwróć uwagę w szczególności, że pierwsza instrukcja nie wpłynie na właściwość localStorage.length(z wyjątkiem być może jej zwiększenia, jeśli nie ma 'length'już klucza localStorage). Pod tym względem specyfikacja wydaje się być wewnętrznie niespójna.

Jednak następujące elementy prawdopodobnie nie zrobią tego, co chcesz:

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

Co ciekawe, pierwszy nie działa w Chrome, ale jest synonimem wywołania funkcjonalnego w Firefoksie. Drugi zawsze rejestruje liczbę obecnych kluczy localStorage.

* Dotyczy to przede wszystkim przeglądarek obsługujących przechowywanie danych w Internecie. (Dotyczy to prawie wszystkich nowoczesnych przeglądarek na komputery stacjonarne i urządzenia mobilne). W przypadku środowisk symulujących przechowywanie lokalne przy użyciu plików cookie lub innych technik zachowanie zależy od zastosowanej podkładki. Kilka polyfillów localStoragemożna znaleźć tutaj .

Ted Hopp
źródło
11

Pytanie jest już dość stare, ale skoro zostałem w nim zacytowany, myślę, że powinienem powiedzieć dwa słowa o moim stwierdzeniu.

Obiekt Storage jest raczej szczególny, jest to obiekt, który zapewnia dostęp do listy par klucz / wartość. Dlatego nie jest to zwykły obiekt ani tablica.

Na przykład ma atrybut length, który w przeciwieństwie do atrybutu długości tablicy jest tylko do odczytu i zwraca liczbę kluczy w pamięci.

Za pomocą tablicy możesz:

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

Tutaj mamy pierwszy powód, aby używać metod pobierających / ustawiających. Co jeśli chcesz ustawić element o nazwie 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"

W przypadku innych elementów obiektu Storage jest to jeszcze bardziej krytyczne, ponieważ są one zapisywalne i możesz przypadkowo nadpisać metody, takie jak getItem. Korzystanie z metod API zapobiega którymkolwiek z tych możliwych problemów i zapewnia spójny interfejs.

Ciekawym punktem jest również następujący akapit w specyfikacji (podkreślony przeze mnie):

Metody setItem () i removeItem () muszą być atomowe w odniesieniu do niepowodzenia. W przypadku niepowodzenia metoda nic nie daje. Oznacza to, że zmiany w obszarze przechowywania danych muszą albo zakończyć się sukcesem, albo obszar przechowywania danych nie może być w ogóle zmieniany.

Teoretycznie nie powinno być różnicy między pobierającymi / ustawiającymi wartościami a []dostępem, ale nigdy nie wiadomo ...

Christoph
źródło
Po pierwsze, do cholery, prawie wszystko w JavaScript jest zapisywalne, a interfejs API localStorage ma tylko trzy właściwości, o których jestem świadomy. Po drugie, używając metod notacji z kropką lub nawiasem, nadal trafiasz na jakąś implementację natywnego setera, ponieważ wartości są automatycznie konwertowane na ciągi bez względu na to, jak je ustawisz, więc powinny mieć dostępne te same zabezpieczenia. Właściwie nigdy wcześniej nie słyszałem o uszkodzeniu trwałej wartości w scenariuszu przeglądarki po stronie klienta. Podejrzewam, że nawet akcesoria waniliowe zazwyczaj mają jakieś zabezpieczenie.
Erik Reppen
Kwestia kolizji nazw jest doskonała. lengthNieruchomość nie zmieni się (przynajmniej w Chrome i Firefox [*]), jeśli zadzwonisz localStorage.setItem("length", something);, ale można pobrać somethingz localStorage.getItem("length");. Co ciekawe, przypisanie localStorage.length = something;w Chrome nie jest opcją, ale w Firefoksie będzie przechowywane somethingpod kluczem "length"(który możesz wtedy pobrać tylko za pomocą funkcjonalnego interfejsu). [*] Właściwie w przeglądarce Firefox lengthwłaściwość ulegnie zmianie, jeśli klucza "length"nie ma localStorage.
Ted Hopp
@ErikReppen - Według specyfikacji , localStoragema sześć predefiniowanych właściwości: length, key, getItem, setItem, removeItem, i clear.
Ted Hopp
1

Wiem, że to stary post, ale ponieważ nikt tak naprawdę nie wspomniał o wydajności, skonfigurowałem kilka testów JsPerf, aby go porównać, a także będąc spójnym interfejsem, getItema setItemtakże konsekwentnie szybszym niż używanie notacji kropkowej lub nawiasów, a także znacznie łatwiejszym do odczytania.

Oto moje testy na JsPerf

Dave Mackintosh
źródło
Ur jsPerf nie uwzględnił nawiasów w swoim teście. Dodałem je i uruchomiłem kilka testów, wydajność zależy od przeglądarki. zarówno na Chrome, jak i Firefox, getItemi setItembyły najwolniejsze w każdej kategorii, przy czym kropka była najszybsza w przeglądarce Chrome, a nawias najszybszy w przeglądarce Firefox. Myślę też, że „bycie znacznie łatwiejszym do odczytania” jest całkowicie subiektywne ... tak, określa funkcję, którą wykonuje, ale każdy, kto kiedykolwiek pracował ze zmiennymi obiektowymi lub tablicowymi, wiedziałby w pół sekundy, co się dzieje z kropką / nawiasem.
PlantTheIdea
Masz rację, w czasie pisania tych testów metody pobierające i ustawiające były konsekwentnie szybsze niż notacja kropkowa. Już nie. Kiedy dostanę 5 minut, wrócę i zaktualizuję tę odpowiedź. Dziękuję za zwrócenie uwagi.
Dave Mackintosh
0

Jak już wspomniano, nie ma prawie żadnej różnicy poza nieistniejącym kluczem. Różnica w wydajności różni się w zależności od przeglądarki / OS używasz. Ale tak naprawdę nie jest tak inaczej.

Sugeruję użycie standardowego interfejsu tylko dlatego, że jest to zalecany sposób korzystania z niego.

Salvador Dali
źródło
„Sugeruję użycie standardowego interfejsu” - oba interfejsy są określone w standardzie.
Ted Hopp,
@TedHopp Myślę, że tylko setItem i getItem są określone w standardzie .
Salvador Dali,
2
Przeciwnie. Ze standardu: „Obsługiwane nazwy właściwości w obiekcie pamięci masowej to klucze każdej pary klucz / wartość obecnie znajdującej się na liście skojarzonej z obiektem, w kolejności, w jakiej klucze zostały ostatnio dodane do obszaru pamięci”.
Ted Hopp,