92

我最近问了一个关于 LocalStorage 的问题。尚未设置该项目时,使用JSON.parse(localStorage.item)and JSON.parse(localStorage['item'])were not working 返回。NULL

然而,JSON.parse(localStorage.getItem('item')确实奏效了。事实证明,JSON.parse(localStorage.testObject || null)也有效。

其中一条评论基本上是这样说的,localStorage.getItem()并且localStorage.setItem()应该始终首选:

getter 和 setter 提供了一种一致的、标准化的和跨浏览器兼容的方式来使用 LS api,并且应该始终优先于其他方式。-克里斯托夫

我开始喜欢对 localStorage 使用速记点和括号表示法,但我很想知道其他人对此的看法。localStorage.getItem('item') 是否比 localStorage.item 或 localStorage['item'] 更好,或者只要它们有效,速记符号就可以了吗?

4

4 回答 4

91

直接属性访问(localStorage.itemlocalStorage['item'])和使用功能接口(localStorage.getItem('item'))都可以正常工作。两者都是标准的和跨浏览器兼容的。*根据规格

Storage 对象上支持的属性名称是当前存在于与该对象关联的列表中的每个键/值对的键,按照键最后添加到存储区域的顺序。

当没有找到具有请求名称的键/值对时,它们的行为会有所不同。例如,如果 key'item'不存在,var a = localStorage.item;将导致abe undefined,而var a = localStorage.getItem('item');将导致avalue null。正如您所发现的,undefinednullJavaScript/EcmaScript 中不可互换。:)

编辑:正如 Christoph 在他的回答中指出的那样,功能接口是在等于预定义属性的键下可靠地存储和检索值的唯一方法localStorage。(其中有六个:lengthkeysetItemgetItemremoveItemclear。)因此,例如,以下将始终有效:

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

请特别注意,第一条语句不会影响该属性localStorage.length(如果 中没有键,则可能会增加它'length'localStorage。在这方面,规范似乎在内部不一致。

但是,以下内容可能不会满足您的要求:

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

有趣的是,第一个是 Chrome 中的无操作,但与 Firefox 中的函数调用同义。第二个将始终记录localStorage.

* 对于一开始就支持 Web 存储的浏览器来说,情况确实如此。(这几乎包括所有现代桌面和移动浏览器。)对于使用 cookie 或其他技术模拟本地存储的环境,行为取决于所使用的 shim。localStorage可以在这里找到几个 polyfill 。

于 2013-03-15T17:53:55.217 回答
13

这个问题已经很老了,但是既然我在问题中被引用了,我想我应该对我的陈述说两句话。

存储对象相当特殊,它是一个对象,它提供对键/值对列表的访问。因此它不是一个普通的对象或数组。

例如,它具有长度属性,与数组长度属性不同,它是只读的,并返回存储中键的数量。

使用数组,您可以:

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

在这里,我们有第一个理由使用 getter/setter。如果你想设置一个名为 的项目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() 方法对于失败必须是原子的。在失败的情况下,该方法什么也不做。即,数据存储区的改变必须要么成功,要么根本不能改变数据存储区。

从理论上讲,getter/setter 和访问之间应该没有区别[],但你永远不知道......

于 2014-07-23T07:59:15.377 回答
2

我知道这是一篇旧文章,但由于没有人真正提到性能,我设置了一些 JsPerf 测试来对其进行基准测试,并且作为一个连贯的接口getItem,并且setItem始终比使用点符号或括号更快并且更容易阅读。

这是我对 JsPerf的测试

于 2013-06-09T09:57:00.777 回答
0

如前所述,除了不存在的密钥之外几乎没有区别。性能差异取决于您使用的浏览器/操作系统。但这并没有那么不同。

我建议你使用标准接口,只是因为它是一种推荐的使用方式。

于 2014-03-23T05:45:14.080 回答