localStorage.getItem('item') 是不是优于 localStorage.item 或 localStorage['item']?
Posted
技术标签:
【中文标题】localStorage.getItem(\'item\') 是不是优于 localStorage.item 或 localStorage[\'item\']?【英文标题】:Is localStorage.getItem('item') better than localStorage.item or localStorage['item']?localStorage.getItem('item') 是否优于 localStorage.item 或 localStorage['item']? 【发布时间】:2012-09-19 21:26:09 【问题描述】:我最近问过a question about LocalStorage。当项目尚未设置时,使用 JSON.parse(localStorage.item)
和 JSON.parse(localStorage['item'])
无法返回 NULL
。
但是,JSON.parse(localStorage.getItem('item')
确实有效。事实证明,JSON.parse(localStorage.testObject || null)
也有效。
One of the comments 基本上说localStorage.getItem()
和localStorage.setItem()
应该总是首选:
getter 和 setter 提供了一致的、标准化的和 使用 LS api 的跨浏览器兼容方式,并且应该始终 优于其他方式。 -Christoph
我开始喜欢对 localStorage 使用速记点和括号表示法,但我很想知道其他人对此的看法。 localStorage.getItem('item') 是否比 localStorage.item 或 localStorage['item'] 更好,或者只要它们有效,速记符号就可以了吗?
【问题讨论】:
我相信克里斯托夫已经把他的推理说得很清楚了。getItem
和 setItem
是 standardised 的做事方式。
我明白了。略过这些建议太困了,但由于这个 webstorage API 相对较新,我个人会坚持使用正确记录的 getItem
/setItem
方法。稍后我会再次阅读规范,但回答您的问题的唯一防故障方法是在所有主要浏览器上进行整个测试。
规范说“存储对象上支持的属性名称是当前存在于与该对象关联的列表中的每个键/值对的键。”这不是让localStorage.item
也标准化了吗?
@Barmar 回复有点晚,但是在看到这么多这个问题的傻瓜并回到这里之后,我会回复你是绝对正确的。但是,我会再次推荐使用getItem
/setItem
,因为这些方法不会与localStorage
对象的现有属性冲突。示例:localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));
有效,而 localStorage.getItem = 'blah';
将覆盖 localStorage 的 getItem
方法。 jsfiddle.net/DrquY
我还没有看到任何支持我的方法的论据。像往常一样使用名称/值对。当我们使用 get/set 方法时,另一个给我们空值。我想如果我要与另一个具有 null 的可选值的值列表进行比较,一个值会比另一个更有意义,但是当它们都在规范中时说一个或另一个是“首选”是愚蠢的,IMO。提供这两种方法都是有原因的。
【参考方案1】:
直接属性访问(localStorage.item
或 localStorage['item']
)和使用功能接口(@987654326@)都可以正常工作。两者都是标准的和跨浏览器兼容的。*根据the spec:
Storage 对象上支持的属性名称是当前存在于与该对象关联的列表中的每个键/值对的键,按照键最后添加到存储区域的顺序。
当没有找到具有请求名称的键/值对时,它们的行为会有所不同。例如,如果键 'item'
不存在,var a = localStorage.item;
将导致 a
为 undefined
,而 var a = localStorage.getItem('item');
将导致 a
具有值 null
。正如您所发现的,undefined
和 null
在 javascript/EcmaScript 中不可互换。 :)
编辑: 正如 Christoph 在his answer 中指出的那样,函数式接口是在等于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 或其他技术模拟本地存储的环境,行为取决于所使用的 shim。 localStorage
的几个 polyfill 可以在 here 找到。
【讨论】:
【参考方案2】:我知道这是一篇旧帖子,但由于没有人真正提到性能,我设置了一些 JsPerf 测试来对其进行基准测试,并且作为一个连贯的接口 getItem
和 setItem
也始终比使用点符号或括号更快并且更容易阅读。
这是我的测试on JsPerf
【讨论】:
你的 jsPerf 在其测试中没有包含括号。我已经添加了它们并运行了一些测试,性能是基于浏览器的。在 chrome 和 firefox 上,getItem
和 setItem
在每个类别中都是最慢的,dot 在 chrome 上最快,而在 firefox 上括号最快。我还认为“更容易阅读”完全是主观的......是的,它说明了它的执行功能,但是任何曾经使用过对象或数组变量的人都会在半秒内知道点/括号发生了什么。跨度>
你是对的,在编写这些测试时,getter 和 setter 始终比点表示法快。现在不是这样了。当我得到 5 分钟时,我会回来更新这个答案。感谢您指出这一点。【参考方案3】:
如前所述,除了不存在的密钥之外几乎没有区别。 difference in performance varies 取决于您使用的浏览器/操作系统。但实际上并没有那么不同。
我建议你使用标准接口,只是因为它是一种推荐的使用方式。
【讨论】:
“我建议你使用标准接口” - 两个接口都在标准中指定。 @TedHopp 我认为只有 setItem 和 getItem 是specified in the standard。 相反。来自标准:“存储对象上支持的属性名称是当前存在于与对象关联的列表中的每个键/值对的键,按照键最后添加到存储区域的顺序。” 【参考方案4】:这个问题已经很老了,但是既然我在问题中被引用了,我想我应该就我的陈述说两句话。
存储对象比较特殊,它是一个对象,提供对键/值对列表的访问。因此它不是一个普通的对象或数组。
比如它有length属性,不像数组length属性是只读的,返回存储中key的个数。
使用数组你可以做到:
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 和[]
访问之间应该没有区别,但你永远不知道......
【讨论】:
第一点,该死的 JavaScript 中几乎所有东西都是可写的,而 localStorage API 只有三个我知道的属性。其次,使用点或括号表示法,您仍然会遇到某种本机 setter 实现,因为无论您如何设置它们,这些值都会自动转换为字符串,因此它应该具有相同的保护措施。实际上,我以前从未听说过持久值在客户端浏览器场景中被破坏。我怀疑即使是普通访问器通常也有某种保护措施。 关于名称冲突的观点非常好。如果您调用localStorage.setItem("length", something);
,length
属性不会改变(至少在 Chrome 和 Firefox[*] 中),但您可以使用 localStorage.getItem("length");
检索 something
。有趣的是,在 Chrome 中分配 localStorage.length = something;
是无操作的,但在 Firefox 中,它会将 something
存储在键 "length"
下(然后您只能使用功能接口检索)。 [*] 实际上,在 Firefox 中,如果键 "length"
不在 localStorage
中,length
属性将发生变化。
@ErikReppen - 根据the spec,localStorage
有六个预定义属性:length
、key
、getItem
、setItem
、removeItem
和 clear
。 以上是关于localStorage.getItem('item') 是不是优于 localStorage.item 或 localStorage['item']?的主要内容,如果未能解决你的问题,请参考以下文章
将 localStorage.getItem() 与打字稿一起使用
localStorage - 使用 getItem/setItem 函数或直接访问对象?
localstorage.getitem('key') 有时返回 null - 在反应应用程序中
vars 在 localStorage.getItem('key') 之后没有保持正确的值