# localStorage、sessionStorage與cookie
## 個別差異
### cookie
1. 大小約 4kb
2. 當瀏覽器發送 Request 到 Server 之後,回傳的 Response header 之中會帶有一個 Set-Cookie 的資料,只要瀏覽器看到這個資料,就會把 Cookie 寫進來。
3. 當瀏覽器再發送 Reqeust 時,會自動把 cookie 帶到 Server 端。
4. 為了讓 Server 可以辨識使用者身份,所有 request 都會自動把該 domain 的 Cookie 帶上去。
### localStorage
1. key - value 形式,key 跟 value 都只能存字串,如果是 object 或 number 會自動轉換成 string
2. 瀏覽器上查看方式
* Chrome: F12 > Application > LocalStorage
3. 大小預設有 5mb
4. 不像 Cookie 會隨著 Request 送到 Server 端,Storage 只作用在 Client 端瀏覽器,故也可以降低網路流量
5. 生命週期(沒有過期時間,除非手動刪除),清空localStorage時機
* 域名異動(三級域名.主域名.頂域名): 三級域名、主域名、頂域名異動皆會清空
* 開無痕視窗: 清空
* F5 刷新: 不清空
* Ctrl+F5: 不清空
* 開新頁簽: 不清空
* 關閉瀏覽器在開啟: 不清空
#### 實際操作
```javascript
//localStorage
//存資料
localStorage.setItem('Account', 'aaa')
//取資料
localStorage.getItem('Account')
//移除特定資料
localStorage.removeItem('Account');
//一口氣全部清除
localStorage.clear();
```
### sessionStorage
1. 除清空時機外,其他機制與localStorage相同
2. 清空localStorage時機
* 域名異動(三級域名.主域名.頂域名): 三級域名、主域名、頂域名異動皆會清空
* 開無痕視窗: 清空
* 開新頁簽(不是用複製的): 清空
* 關閉瀏覽器在開啟: 清空
* F5 刷新: 不清空
* Ctrl+F5: 不清空
* 開新頁簽(用複製的): 不清空
#### 實際操作
```javascript
//sessionStorage
//存資料
sessionStorage.setItem('Account', value)
//取資料
sessionStorage.getItem('Account')
//移除特定資料
sessionStorage.removeItem('Account')
//一口氣全部清除
sessionStorage.clear();
```
## 簡單實測
## 支援度測試
### 手機
* chrome
* 小米
* 三星
* UC (很頓)
* 百度(無痕可)
* firefox(無痕可,但與非無痕不通用)
* QQ(無痕可,遇過幾次還沒塞到上限制程式就crash)
* edge(無痕可,但與非無痕不通用)
* 遨遊(無痕可)
* opera(無痕可,但與非無痕不通用)
* 360(無痕可)
* 獵豹(無痕可,無法測試極限直)
* 搜狗>>載不到apk
### PC
* chrome (無痕可正常使用與非無痕不通用)
* firefox(無痕可正常使用與非無痕不通用)
* UC (無痕可正常使用與非無痕不通用)
* edge
* QQ(無痕可正常使用與非無痕通用)
```htmlmixed
<html><head>
<meta charset="utf-8">
<title>webStorage 測試</title>
<meta name="keywords" content="html5, html 5, storage, localStorage, limit, quota, test, browser, opera, chrome, firefox, explorer, adjust, change">
<meta name="description" content="This page tries to detect how many characters your browser may save to window.localStorage. Accuracy is 2 first digits.">
<style>body {max-width: 30em; margin:auto;}</style>
<link rel="author" href="https://arty.name">
</head>
<body>
<h1>userAgent</h1>
<div id="userAgent"></div>
<h1>localStorage </h1>
<div id="supportLocalStorage">支援</div>
<h1>sessionStorage</h1>
<div id="supportSessionStorage">支援</div>
<h1>localStorage 簡易測試</h1>
<div id="resultsEasy"></div>
<div>
<button type="button" style="width:30%;height:10%;font-size:20px;" onclick="localStorage.removeItem('resultsEasy');">removeItem</button>
<button type="button" style="width:30%;height:10%;font-size:20px;" onclick="localStorage.setItem('resultsEasy', 'aaa');">setItem</button>
<button type="button" style="width:30%;height:10%;font-size:20px;" onclick="resultsEasy.innerHTML = localStorage.getItem('resultsEasy');">getItem</button>
</div>
<h1>localStorage 儲存上限</h1>
<div id="results"></div>
<div>
<button type="button" style="width:30%;height:10%;font-size:20px;" onclick="localStorage.removeItem('difficulty');results.innerHTML =''">清除</button>
<button type="button" style="width:30%;height:10%;font-size:20px;" onclick="results.innerHTML ='開始';Difficulty();">開始</button>
</div>
<script>
var iterationsData;
var userAgent = document.getElementById('userAgent');
var results = document.getElementById('results');
var resultsEasy = document.getElementById('resultsEasy');
var supportLocalStorage = document.getElementById('supportLocalStorage');
var supportSessionStorage = document.getElementById('supportSessionStorage');
var storageTest = function () {
var test = function (storage) {
if (!!storage) {
try {
storage.setItem('storageTest', 'value')
if (storage.getItem('storageTest') !== 'value') {
storage.removeItem('storageTest');
throw '您的瀏覽器處於無痕模式,請退出無痕模式後再重新打開本頁面'
}
storage.removeItem('storageTest');
return { valid: true }
} catch (e) {
console.log(e)
return { valid: false, msg: e }
}
} else {
console.log('您的瀏覽器不支持本地存儲')
return { valid: false, msg: '您的瀏覽器不支持本地存儲' };
}
}
return {
localStorage: test(window.localStorage),
sessionStorage: test(window.sessionStorage)
}
};
function Difficulty(){
var n10b = '0123456789';
var n100b = repeat(n10b, 10);
var n1kib = repeat(n100b, 10);
var n10kib = repeat(n1kib, 10);
var n100kib = repeat(n10kib, 10);
var n1mib = repeat(n100kib, 10);
var n10mib = repeat(n1mib, 10);
var values = [n10b, n100b, n1kib, n10kib, n100kib, n1mib, n10mib];
iterationsData = [];
for (var majorIndex = 1; majorIndex < values.length; majorIndex++) {
var major = values[majorIndex];
var minor = values[majorIndex - 1];
for (var i = 1; i < 10; i++) {
for (var j = 0; j < 10; j++) {
iterationsData.push([major, minor, i, j]);
}
}
}
var index = 0;
var oldLength = 0;
function iteration() {
var data = iterationsData[index];
major = data[0];
minor = data[1];
i = data[2];
j = data[3];
var string = repeat(major, i) + repeat(minor, j);
var length = '' + string.length;
if (test(string)) {
//results.innerHTML = length + ' characters were stored successfully.';
} else {
results.innerHTML = oldLength + ' characters were stored successfully, but ' + length + ' weren\'t.';
return;
}
oldLength = length;
index++;
if (index < iterationsData.length) {
setTimeout(iteration, 0);
} else {
results.innerHTML = oldLength + ' characters were saved successfully, test is stopped.';
}
}
function test(value) {
try {
localStorage.test = value;
return true;
} catch (e) {
return false;
}
}
function repeat(string, count) {
var array = [];
while (count--) {
array.push(string);
}
return array.join('');
}
iteration();
}
(function () {
userAgent.innerHTML = navigator.userAgent;
if (!storageTest().localStorage) {
supportLocalStorage.innerHTML = '不支援';
return;
}
if (!storageTest().sessionStorage) {
supportSessionStorage.innerHTML = '不支援';
return;
}
})();
</script>
</body></html>
```