localStorage.getItem('item') 是否比 localStorage.item 或 localStorage['item'] 好?

IT技术 javascript syntax local-storage
2021-01-26 00:03:20

我最近问了一个关于 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'] 更好,或者只要它们有效,速记符号就可以吗?

4个回答

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

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

当没有找到具有请求名称的键/值对时,它们的行为会有所不同。例如,如果 key'item'不存在,var a = localStorage.item;将导致ais undefined,而var a = localStorage.getItem('item');将导致a具有 value null正如你所发现的,undefinednull不是在JavaScript / 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可以在这里找到几个 polyfills

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

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

例如它有长度属性,它不像数组长度属性是只读的,它返回存储中的键数。

使用数组,您可以执行以下操作:

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 和[]访问之间应该没有区别,但你永远不知道......

关于名称冲突的观点非常好。length属性将不会改变(至少在Chrome和Firefox [*])如果你打电话localStorage.setItem("length", something);,但你可以检索something使用localStorage.getItem("length");有趣的是,localStorage.length = something;在 Chrome 中分配是一个空操作,但在 Firefox 中它将存储something在密钥下"length"(然后您只能使用功能界面检索)。[*] 实际上,在 Firefox 中,length如果密钥"length"不在localStorage.
2021-03-17 00:03:20
在第一点上,该死的 JavaScript 中几乎所有东西都是可写的,而 localStorage API 只有三个我知道的属性。在第二种情况下,使用点或括号表示法,您仍然会遇到某种本机 setter 实现,因为无论您如何设置它们,这些值都会自动转换为字符串,因此它应该具有相同的保护措施。实际上,我以前从未听说过在客户端浏览器场景中持久值会被破坏。我怀疑即使是普通的访问者通常也有某种保护措施。
2021-03-24 00:03:20
@ErikReppen -根据该规范localStorage有六个预定义的属性:lengthkeygetItemsetItemremoveItem,和clear
2021-04-02 00:03:20

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

这是我对 JsPerf 的测试

你的 jsPerf 在它的测试中没有包含括号。我已经添加了它们并运行了一些测试,性能是基于浏览器的。在 chrome 和 firefox 上,getItem并且setItem在每个类别中都是最慢的,chrome 上的 dot 最快,firefox 上的括号最快。我也认为“更容易阅读”完全是主观的......是的,它说明了它的功能,但是任何曾经使用过对象或数组变量的人都会在半秒内知道点/括号发生了什么。
2021-03-25 00:03:20
您说得对,在编写这些测试时,getter 和 setter 始终比点表示法快。现在不是这样了。当我得到 5 分钟时,我会回来更新这个答案。感谢您指出了这一点。
2021-03-29 00:03:20

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

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

相反。来自标准:“存储对象上支持的属性名称是当前存在于与对象关联的列表中的每个键/值对的键,按照键最后添加到存储区域的顺序。”
2021-03-20 00:03:20
“我建议您使用标准接口” -标准中指定了两个接口。
2021-03-24 00:03:20
@TedHopp 我认为标准中只指定了setItem 和 getItem
2021-04-13 00:03:20