# 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> ```