1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
---
title: LocalStorage
slug: conflicting/Web/API/Window/localStorage
tags:
- 存储API
- 离线
translation_of: Web/API/Window/localStorage
translation_of_original: Web/API/Web_Storage_API/Local_storage
original_slug: Web/API/Storage/LocalStorage
---
<p><code>localStorage</code> 与<code> <a href="/en-US/docs/Web/API/sessionStorage">sessionStorage</a></code> 一样,都遵循同源策略,但是它是持续存在的。<code>localStorage</code> 首次出现于 Firefox 3.5。</p>
<div class="note"><strong>Note:</strong> 当浏览器进入隐私浏览模式,会创建一个新的、临时的数据库来存储local storage的数据;当关闭隐私浏览模式时,该数据库将被清空并丢弃。</div>
<pre class="brush:js" style="font-size: 14px;">// Save data to the current local store
localStorage.setItem("username", "John");
// Access some stored data
alert( "username = " + localStorage.getItem("username"));</pre>
<p class="note">本地存储(<code>localStorage</code>)的持续存在对许多事情都有帮助,包括这个示例<a href="http://codepen.io/awesom3/pen/Hlfma">this tutorial on Codepen</a>所演示的记录页面查看次数。</p>
<h4 id="兼容性" style="line-height: 18px; font-size: 1.28571428571429rem;">兼容性</h4>
<p><code>Storage</code> 对象最近才加入标准,因此可能并不被所有浏览器支持。你可以通过在你的scripts代码前加入以下两段代码中某一段来规避在不能原生支持的执行环境使用<code>localStorage</code>对象的问题。</p>
<p>该算法借助于cookies,对localStorage对象进行了严谨的实现。</p>
<pre class="brush: js" style="font-size: 14px;">if (!window.localStorage) {
Object.defineProperty(window, "localStorage", new (function () {
var aKeys = [], oStorage = {};
Object.defineProperty(oStorage, "getItem", {
value: function (sKey) { return sKey ? this[sKey] : null; },
writable: false,
configurable: false,
enumerable: false
});
Object.defineProperty(oStorage, "key", {
value: function (nKeyId) { return aKeys[nKeyId]; },
writable: false,
configurable: false,
enumerable: false
});
Object.defineProperty(oStorage, "setItem", {
value: function (sKey, sValue) {
if(!sKey) { return; }
document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
},
writable: false,
configurable: false,
enumerable: false
});
Object.defineProperty(oStorage, "length", {
get: function () { return aKeys.length; },
configurable: false,
enumerable: false
});
Object.defineProperty(oStorage, "removeItem", {
value: function (sKey) {
if(!sKey) { return; }
document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
},
writable: false,
configurable: false,
enumerable: false
});
this.get = function () {
var iThisIndx;
for (var sKey in oStorage) {
iThisIndx = aKeys.indexOf(sKey);
if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); }
else { aKeys.splice(iThisIndx, 1); }
delete oStorage[sKey];
}
for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); }
for (var aCouple, iKey, nIdx = 0, aCouples = document.cookie.split(/\s*;\s*/); nIdx < aCouples.length; nIdx++) {
aCouple = aCouples[nIdx].split(/\s*=\s*/);
if (aCouple.length > 1) {
oStorage[iKey = unescape(aCouple[0])] = unescape(aCouple[1]);
aKeys.push(iKey);
}
}
return oStorage;
};
this.configurable = false;
this.enumerable = true;
})());
}
</pre>
<div class="note"><strong>注意:</strong>数据的最大大小是通过cookies来严格限制的。可以使用这样的算法实现,使用<code>localStorage.setItem()</code>和<code>localStorage.removeItem()</code>这两个函数进行添加、改变或删除一个键。使用方法为<code>localStorage.yourKey = yourValue;和delete localStorage.yourKey;</code>进行设置和删除一个键<strong>并不是安全的做法</strong>。您也可以改变它的名字和使用它仅仅去管理文档的cookies而不管<code>localStorage </code>这个对象。</div>
<div class="note"><strong>注意:</strong>通过将字符串<code style="background: rgb(204, 204, 204);">"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"</code> 改成<code style="background: rgb(204, 204, 204);">"; path=/"</code>(并且改变对象的名字),可以使得这个 <code>localStorage</code>的实现变为<code>sessionStorage</code>的实现。然而,这种实现方式会使储存键值可以跨标签和窗口访问(而且只会在浏览器窗口被关闭时销毁),完全兼容的<code>sessionStorage</code>实现会将储存键值访问权限限定在当前浏览上下文。</div>
<p>下面是另一个,并不那么严谨的<code>localStorage</code>对象的实现。相比上一个方法,它更简单且能与旧的浏览器良好兼容,如Internet Explorer < 8 (甚至能在<strong> Internet Explorer 6 上正常工作</strong>)。它同样是使用cookies来实现的。</p>
<pre class="brush:js" style="font-size: 14px;">if (!window.localStorage) {
window.localStorage = {
getItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) { return null; }
return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
},
key: function (nKeyId) {
return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]);
},
setItem: function (sKey, sValue) {
if(!sKey) { return; }
document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
this.length = document.cookie.match(/\=/g).length;
},
length: 0,
removeItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) { return; }
document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
this.length--;
},
hasOwnProperty: function (sKey) {
return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
}
};
window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length;
}
</pre>
<div class="note"><strong>注意:</strong>数据量的最大值是通过cookies来严格限制的。可以使用<code>localStorage.getItem()</code>, <code>localStorage.setItem()</code>和<code>localStorage.removeItem()</code>等方法获取、设置或删除一个键。使用方法<code>localStorage.yourKey = yourValue;</code>获取、添加、改变或者删除一个键<strong>并不是安全的做法</strong>。您也可以改变它的名字和使用它仅仅去管理文档的cookies而不管<code>localStorage </code>这个对象。</div>
<div class="note"><strong>注意:</strong>通过将字符串<code style="background: rgb(204, 204, 204);">"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"</code> 改成<code style="background: rgb(204, 204, 204);">"; path=/"</code>(并且改变对象的名字),可以使得这个 <code>localStorage</code>的实现变为<code>sessionStorage</code>的实现。然而,这种实现方式会使储存键值可以跨标签和窗口访问(而且只会在浏览器窗口被关闭时销毁),完全兼容的sessionStorage实现会将储存键值限定在当前浏览环境上下文。</div>
<h4 id="与globalStorage的兼容性及关系" style="line-height: 18px; font-size: 1.28571428571429rem;">与globalStorage的兼容性及关系</h4>
<p class="note"><code>localStorage</code> 和 <code>globalStorage[location.hostname]</code> 是一样的, 除了作用域是在 HTML5 origin (结构 + 主机名 + 非标准的端口), 并且 <code>localStorage</code> 是一个 <code>Storage</code> 实例 ,而<code>globalStorage[location.hostname]</code> 是一个 <code>StorageObsolete</code> 实例,下面将要讨论这个。 例如, <a class="external" href="http://example.com" rel="freelink">http://example.com</a> 无法访问与 <a class="link-https" href="https://example.com" rel="freelink">https://example.com</a> 相同的 <code>localStorage</code> 对象 ,但是它们可以访问同一个 <code>globalStorage</code>. <code>localStorage</code> 是标准的接口,<code>globalStorage</code> 不是, 所以不要依赖于 <code>globalStorage</code> 。 </p>
<p>请注意,给globalStorage[location.hostname]设置一个属性并不会影响到localStorage。拓展<code>Storage.prototype</code>也不会影响<code>globalStorage</code>对象,只有拓展<code>StorageObsolete.prototype</code>才会影响。</p>
<h4 id="存储格式">存储格式</h4>
<p><code>Storage</code>的键和值都是以每个字符占2个字节的UTF-16字符串(<a href="/zh-CN/docs/Web/API/DOMString">DOMString</a>)格式存储的。</p>
|