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()应始终优先考虑:

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

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


我相信克里斯托夫(Christoph)已经使他的推理非常清楚。getItem并且setItem标准化的处理方式。
法布里西奥磨砂

1
我懂了。几乎不会困倦地浏览这些建议,但是由于此Webstorage API相对较新,因此我个人会坚持使用正确记录的getItem/setItem方法。我将在以后再次阅读规格,但是回答您问题的唯一防故障方法是在所有主要浏览器上进行整个测试。
法布里西奥磨砂

4
该规范说:“存储对象上受支持的属性名称是与该对象关联的列表中当前存在的每个键/值对的键。” 难道不是也localStorage.item标准化了吗?
Barmar 2012年

2
@Barmar稍晚的回复,但是在看到这个问题的很多重复并回到这里之后,我会回复你是绝对正确的。但是,我将再次建议使用getItem/,setItem因为这些方法不会与localStorage对象的现有属性冲突。示例:localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));有效,而localStorage.getItem = 'blah';将覆盖localStorage的getItem方法。jsfiddle.net/DrquY
法布里西奥磨砂

1
我仍然没有看到支持这两种方法的论点赢得了我的认可。一个名称/值对一如既往。当使用get / set方法时,另一个为我们提供了null。我想,如果将我与另一个对可选值都为空的值列表进行比较,则一个将比另一个更有意义,但是说,当两者在规范中都是愚蠢的时,IMO便说“一个”或“另一个”是“首选的”。两种方法之所以可用是有原因的。
埃里克·雷彭

Answers:


83

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

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

当找不到带有所请求名称的键/值对时,它们的行为就不同。例如,如果密钥'item'不存在,var a = localStorage.item;将导致a存在undefined,而var a = localStorage.getItem('item');将导致a具有value null。如您所知,undefined并且null在JavaScript / EcmaScript中不可互换。:)

编辑:正如Christoph在他的答案中指出的那样,功能接口是可靠地存储和检索等于的预定义属性的键下的值的唯一方法localStorage。(其中有六个:lengthkeysetItemgetItemremoveItem,和clear。)所以,举例来说,下面将始终工作:

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

请特别注意,第一个语句不会影响物业localStorage.length(如果没有按键,除了可能增加它'length'已经localStorage)。在这方面,该规范似乎在内部不一致。

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

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

有趣的是,第一个是Chrome中的no-op,但与Firefox中的功能调用同义。第二个将始终记录中显示的键数localStorage

* 对于首先支持网络存储的浏览器而言,这是正确的。(这几乎包括所有现代台式机和移动浏览器。)对于使用Cookie或其他技术模拟本地存储的环境,其行为取决于所使用的填充程序。localStorage可以在此处找到几种填充料。


11

这个问题已经很老了,但是由于已经在问题中被引用了,所以我想对我的发言说两个字。

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

例如,它具有length属性,与array 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()方法必须是原子的。在失败的情况下,该方法不执行任何操作。即,必须成功完成对数据存储区域的更改,或者根本不能更改数据存储区域。

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


首先,该死的几乎所有JavaScript内容都是可写的,localStorage API只有三个我知道的属性。第二,使用点或括号表示法,您仍然会遇到某种本机的setter实现,因为无论您如何设置它们,值都会自动转换为字符串,因此它应具有相同的保护措施。实际上,我以前从未听说过持久值在客户端浏览器方案中会损坏。我怀疑甚至香草访问者也通常具有某种保护措施。
Erik Reppen 2014年

关于名称冲突的观点非常好。该length属性将不会改变(至少在Chrome和Firefox [*])如果你打电话localStorage.setItem("length", something);,但你可以检索something使用localStorage.getItem("length");。有趣的是,localStorage.length = something;在Chrome中进行分配是无操作的,但是在Firefox中,分配将存储something在密钥下"length"(然后您只能使用功能界面进行检索)。[*]实际上,在Firefox中,length如果密钥"length"不在中,则属性将更改localStorage
Ted Hopp

@ErikReppen -根据该规范localStorage有六个预定义的属性:lengthkeygetItemsetItemremoveItem,和clear
Ted Hopp

1

我知道这是一个过时的文章,但是由于没有人真正提到性能,因此我建立了一些JsPerf测试来对其进行基准测试,并使其成为一个连贯的界面,getItem并且setItem比使用点符号或方括号始终保持更快的速度,并且易于阅读。

这是我在JsPerf上的测试


您的jsPerf测试中未包含方括号。我已经添加了它们并运行了一些测试,性能基于浏览器。分别在chrome和firefox上,getItem并且setItem在每个类别中速度最慢,在chrome上点是最快的,而在Firefox上是括号最快的。我还认为“易读性”完全是主观的……是的,它说明了其功能,但是曾经使用过对象或数组变量的任何人都将在半秒钟内知道点/括号的情况。
PlantTheIdea 2013年

没错,在编写这些测试时,getter和setter始终比点表示法快。情况不再如此。当我有5分钟的时间时,我会回来并更新此答案。感谢您指出了这一点。
Dave Mackintosh 2013年

0

如前所述,除了不存在的密钥外,几乎没有任何区别。在性能差而变化取决于/ OS,你使用的是什么浏览器。但这并没有那么大的不同。

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


“我建议您使用标准接口” -两个接口均在标准中指定。
泰德·霍普

@TedHopp我认为标准中仅指定了setItem和getItem 。
Salvador Dali

2
反之。根据标准:“存储对象上受支持的属性名称是与该对象相关联的列表中当前存在的每个键/值对的键,按照键最后一次添加到存储区域的顺序。”
Ted Hopp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.