Является ли localStorage.getItem('item') лучше, чем localStorage.item или localStorage ['item']?
Недавно я спросил вопрос о 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 и всегда должен предпочтительнее других способов. - Christoph
Мне понравилось использовать сокращенные точечные и скобковые обозначения для localStorage, но мне любопытно узнать, что другие принимают это. Является ли localStorage.getItem('item') лучше, чем localStorage.item или localStorage ['item'] ИЛИ если они работают, это сокращенные обозначения в порядке?
Ответы
Ответ 1
Как прямой доступ к свойству (localStorage.item
или localStorage['item']
), так и использование функционального интерфейса (getItem('item')
) работают нормально. Оба стандарта и кросс-браузер совместимы. * Согласно спецификации:
Имена поддерживаемых свойств объекта Storage - это ключи каждой пары ключ/значение, присутствующей в данный момент в списке, связанном с объектом, в том порядке, в котором ключи были в последний раз добавлены в область хранения.
Они просто ведут себя по-разному, когда не найдено пары ключ/значение с запрошенным именем. Например, если ключ 'item'
не существует, var a = localStorage.item;
приведет a
undefined
, тогда как var a = localStorage.getItem('item');
приведет к, имеющему значение a
null
. Как вы обнаружили, undefined
и null
не являются взаимозаменяемыми в JavaScript/EcmaScript. :)
РЕДАКТИРОВАТЬ: Как указывает Кристоф в своем ответе, функциональный интерфейс является единственным способом надежного хранения и извлечения значений под ключами, равными предопределенным свойствам localStorage
. (Есть шесть из них: length
, key
, setItem
, getItem
, removeItem
и clear
.) Так, например, всегда будет работать следующее:
localStorage.setItem('length', 2);
console.log(localStorage.getItem('length'));
В частности, обратите внимание, что первый оператор не повлияет на свойство localStorage.length
(за исключением, возможно, его увеличения, если в localStorage
уже не было ключа 'length'
). В этом отношении спецификация кажется внутренне противоречивой.
Однако следующее, вероятно, не будет делать то, что вы хотите:
localStorage.length = 2;
console.log(localStorage.length);
Интересно, что первый - это неиспользование в Chrome, но оно синонимично с функциональным вызовом в Firefox. Второй всегда будет регистрировать количество ключей, присутствующих в localStorage
.
*Это верно для браузеров, которые в первую очередь поддерживают веб-хранилище.(Это относится практически ко всем современным настольным и мобильным браузерам.) Для сред, которые имитируют локальное хранилище с использованием файлов cookie или других методов, поведение зависит от используемой прокладки.Несколько полифилов для localStorage
можно найти здесь.
Ответ 2
Вопрос уже довольно старый, но, поскольку меня процитировали в этом вопросе, я думаю, что должен сказать два слова о своем заявлении.
Объект хранения является довольно особенным, это объект, который обеспечивает доступ к списку пар ключ/значение. Таким образом, это не обычный объект или массив.
Например, он имеет атрибут длины, который, в отличие от атрибута длины массива, доступен только для чтения и возвращает количество ключей в хранилище.
С массивом вы можете сделать:
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() должны быть атомарными относительно ошибки. В случае неудачи метод ничего не делает. То есть изменения в области хранения данных должны быть либо успешными, либо область хранения данных не должна изменяться вообще.
Теоретически не должно быть никакой разницы между получателями/установщиками и доступом []
, но вы никогда не знаете...
Ответ 3
Я знаю, что это старый пост, но поскольку никто не упоминал о производительности, я установил некоторые тесты JsPerf для его сравнения, а также как последовательный интерфейс getItem
и setItem
также последовательно быстрее, чем использование точечной нотации или скобок а также гораздо легче читать.
Вот мои тесты на JsPerf
Ответ 4
Как уже упоминалось, практически нет разницы, кроме несуществующего ключа. разница в производительности варьируется в зависимости от того, какой браузер/ОС вы используете. Но на самом деле это не так.
Я предлагаю вам использовать стандартный интерфейс, только потому, что это рекомендуемый способ его использования.