Чи є localStorage.getItem ('item') кращим від localStorage.item або localStorage ['item']?


84

Нещодавно я задав питання про LocalStorage . Використовували JSON.parse(localStorage.item)та JSON.parse(localStorage['item'])не працювали для повернення, NULLколи товар ще не встановлено.

Однак JSON.parse(localStorage.getItem('item')справді спрацював. І виявляється, JSON.parse(localStorage.testObject || null)теж працює.

Один із коментарів в основному сказав, що localStorage.getItem()і localStorage.setItem()завжди слід віддавати перевагу:

Геттер та сеттер забезпечують послідовний, стандартизований і сумісний з кросбраузером спосіб роботи з LS api і завжди повинен бути кращим перед іншими способами. - Крістоф

Мені сподобалося використовувати скорочені позначення крапок та дужок для localStorage, але мені цікаво знати, як інші сприймають це. Чи є localStorage.getItem ('item') кращим, ніж localStorage.item або localStorage ['item'] АБО, якщо вони працюють, стислі позначення в порядку?


Я вважаю, що Крістоф чітко висловив свої міркування. getItemі setItemє стандартизованим способом здійснення речей.
Fabrício Matté

1
Розумію. Занадто сонний, щоб проглядати ці рекомендації, але оскільки цей API веб-сховища є відносно новим, я особисто дотримуюсь належним чином задокументованих getItem/ setItemметодів. Я прочитаю технічні характеристики пізніше ще раз, але єдиним безвідмовним способом відповіді на ваше запитання є тестування у всіх основних браузерах.
Fabrício Matté

4
У специфікації сказано: "Підтримувані імена властивостей об’єкта зберігання - це ключі кожної пари ключ / значення, яка в даний час присутня у списку, пов’язаному з об’єктом." Чи це теж не робить localStorage.itemстандартизованим?
Barmar

2
@Barmar Трохи запізніла відповідь, але побачивши стільки дурнів цього питання та повернувшись сюди, я відповім, що ви абсолютно праві. Однак я порекомендую знову використовувати getItem/, setItemоскільки ці методи не суперечать існуючим властивостям localStorageоб'єкта. Приклад: localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));працює, а localStorage.getItem = 'blah';перезапише getItemметод localStorage . jsfiddle.net/DrquY
Fabrício Matté

1
Я досі не бачив аргументів на користь того чи іншого підходу, який би мене підкорив. Можна створити пари ім’я / значення, як вони завжди були. Інший дає нам нульові значення, коли ми використовуємо методи get / set. Я вважаю, якби я порівнював із іншим списком значень, які мали нульові значення для необов’язкових значень, одне мало б більше сенсу, ніж інше, але сказати, що одне або інше є «кращим», коли вони обидва в специфікації нерозумно, IMO. Обидва підходи були доступні з певної причини.
Ерік Реппен

Відповіді:


83

Як прямий доступ до властивостей ( localStorage.itemабо localStorage['item']), так і використання функціонального інтерфейсу ( localStorage.getItem('item')) чудово працюють. Обидва вони є стандартними та сумісними з переглядачами. * Відповідно до специфікації :

Підтримувані імена властивостей об’єкта сховища - це ключі кожної пари ключ / значення, що в даний час присутні у списку, пов’язаному з об’єктом, у тому порядку, коли ключі були останніми додані до області зберігання.

Вони просто поводяться по-різному, коли не знайдено пари ключ / значення із запитаним іменем. Наприклад, якщо ключ 'item'не існує, var a = localStorage.item;це призведе до aіснування undefined, тоді як var a = localStorage.getItem('item');призведе aдо значення null. Як ви виявили, undefinedі nullне є взаємозамінними в JavaScript / EcmaScript. :)

EDIT: Як зазначає Крістоф у своїй відповіді , функціональний інтерфейс - це єдиний спосіб надійно зберігати та отримувати значення під ключами, що дорівнюють заданим властивостям localStorage. (Є шість з них: length, key, setItem, getItem, removeItem, і clear.) Так, наприклад, наступний буде завжди робота:

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

Зверніть увагу , зокрема , що перше твердження не впливатиме на майно localStorage.length( за винятком , можливо , збільшуючи його , якби не було ключа 'length'вже localStorage). У цьому відношенні специфікація здається внутрішньо суперечливою.

Однак наступні, мабуть, не зроблять того, що ви хочете:

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

Цікаво, що перший - це заборона в Chrome, але синонім функціонального виклику у Firefox. Другий завжди реєструє кількість присутніх ключів localStorage.

* Це справедливо для браузерів, які в першу чергу підтримують веб-сховище. (Сюди входять майже всі сучасні настільні та мобільні браузери.) У середовищах, які імітують локальне зберігання за допомогою файлів cookie або інших методів, поведінка залежить від використовуваної обробки. Кілька polyfills для localStorageможна знайти тут .


11

Питання вже досить давнє, але оскільки мене цитували у цьому запитанні, я думаю, що слід сказати два слова щодо мого висловлювання.

Об'єкт зберігання досить особливий, це об'єкт, який забезпечує доступ до списку пар ключ / значення. Таким чином, це не звичайний об'єкт або масив.

Наприклад, він має атрибут length, який на відміну від атрибута length масиву є лише для читання і повертає кількість ключів у сховищі.

За допомогою масиву ви можете зробити:

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

Тут ми маємо першу причину використовувати геттери / сеттери. Що робити, якщо ви хочете встановити елемент під назвою 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"

Для інших членів об'єкта Storage це ще критичніше, оскільки вони доступні для запису, і ви можете випадково перезаписати такі методи, як getItem. Використання методів API запобігає виникненню будь-якої з цих можливих проблем та забезпечує послідовний інтерфейс.

Також цікавим моментом є наступний абзац в специфікації (підкреслений мною):

Методи setItem () та removeItem () повинні бути атомарними щодо відмови. У разі несправності метод нічого не робить. Тобто, зміни в області зберігання даних повинні бути або успішними, або область зберігання даних не повинна змінюватися взагалі.

Теоретично не повинно бути різниці між геттерами / сеттерами та []доступом, але ви ніколи не знаєте ...


По-перше, майже все в JavaScript можна писати, і localStorage API має лише три властивості, про які я знаю. По-друге, використовуючи підходи до позначення крапкою або дужкою, ви все ще вражаєте якусь реалізацію власного сеттера, оскільки значення автоматично перетворюються на рядки, незалежно від того, як ви їх встановили, тому він повинен мати такі ж захисні засоби. Я насправді ніколи раніше не чув про постійне значення, яке пошкоджується в сценарії браузера на стороні клієнта. Я підозрюю, що навіть ванільні аксесуари, як правило, мають якийсь захист.
Ерік Реппен

Суть зіткнення імен є чудовою. lengthВластивість не зміниться (принаймні , в Chrome і Firefox [*]) , якщо ви телефонуєте localStorage.setItem("length", something);, але ви можете отримати somethingз localStorage.getItem("length");. Цікаво, що призначення localStorage.length = something;в Chrome заборонено, але у Firefox воно зберігатиметься somethingпід ключем "length"(який потім можна отримати лише за допомогою функціонального інтерфейсу). [*] Насправді, у Firefox lengthвластивість зміниться, якщо ключ "length"ще не входить localStorage.
Тед Хопп,

@ErikReppen - Згідно специфікації , localStorageмає шість визначених властивостей: length, key, getItem, setItem, removeItem, і clear.
Тед Хопп,

1

Я знаю, що це стара публікація, але оскільки насправді ніхто не згадував продуктивність, я налаштував деякі тести JsPerf, щоб порівняти її, а також будучи цілісним інтерфейсом, getItemа setItemтакож постійно швидший, ніж використання крапкових позначень або дужок, а також набагато легший для читання.

Ось мої тести на JsPerf


ur jsPerf не включав дужки у свій тест. я додав їх і провів кілька тестів, продуктивність базується на браузері. як на chrome, так і на firefox, getItemі setItemбули найповільнішими в кожній категорії, крапка найшвидша на chrome, а дужка найшвидша на firefox. Я також думаю, що "бути набагато легшим для читання" є цілком суб'єктивним ... так, в ньому зазначається функція, яку він виконує, але той, хто коли-небудь працював із змінними об'єкта або масиву, через пів секунди буде знати, що відбувається з точкою / дужкою.
PlantTheIdea

Ви маєте рацію, на момент написання цих тестів геттери та сетери були стабільно швидшими, ніж крапкові позначення. Вже не той випадок. Коли я отримаю 5 хвилин, я повернусь і оновлю цю відповідь. Дякую, що вказали на це.
Дейв Макінтош,

0

Як уже зазначалося, різниці майже немає, за винятком неіснуючого ключа. Різниця в продуктивності варіюється в залежності від того, який браузер / ОС ви використовуєте. Але насправді це не так інакше.

Я пропоную вам використовувати стандартний інтерфейс, лише тому, що це рекомендований спосіб його використання.


"Я пропоную вам використовувати стандартний інтерфейс" - Обидва інтерфейси вказані в стандарті.
Тед Хопп,

@TedHopp Я думаю, що в стандарті вказані лише setItem та getItem .
Сальвадор Далі,

2
Навпаки. Зі стандарту: "Підтримувані імена властивостей об'єкта зберігання - це ключі кожної пари ключ / значення, що в даний час присутні у списку, пов'язаному з об'єктом, у тому порядку, коли ключі востаннє були додані до області зберігання."
Тед Хопп,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.