簡述cookie 、localStorage和sessionStorage

Web Storage規(guī)范

是HTML5的一部分

目的:克服由cookie帶來的一些限制,當(dāng)數(shù)據(jù)需要被嚴(yán)格的控制在客戶端時,無須持續(xù)的將數(shù)據(jù)發(fā)回服務(wù)器。

目標(biāo)

  • 提供一種cookie之外的存儲會話數(shù)據(jù)的途徑
  • 提供一種存儲大量可以跨session存在的數(shù)據(jù)的機(jī)制

定義
Web Storage規(guī)范包含兩種對象的定義:sessionStorage和globalStorage**。這兩個對象在支持的瀏覽器中都是以 window 對象屬性 的形式存在的。
注意:在使用之前記得查看其瀏覽器支持情況

Storage類型

Storage類型的方法:

  • clear(): 刪除所有值
  • getItem(name): 根據(jù)指定的名字 name 獲取對應(yīng)的值
  • setItem(name, value): 為指定的name設(shè)置一個對應(yīng)的值
  • key(index):獲得index位置處的值的名字。
  • removeItem(name):刪除name指定的鍵值對。
    還可以通過length屬性來判斷有多少鍵值對存放在Storage對象中

注意: Storage類型只能存儲字符串。非字符串的數(shù)據(jù)在存儲之前會被轉(zhuǎn)換為字符串

sessionStorage對象

sessionStorage 對象是存儲特定于某個會話的數(shù)據(jù),當(dāng)頁面被重新加載時其仍然存在,只有當(dāng)瀏覽器被關(guān)閉或者當(dāng)前頁面被關(guān)閉時,數(shù)據(jù)才會被清除;可以理解為數(shù)據(jù)被存儲在瀏覽器中,只有瀏覽器被關(guān)閉后,數(shù)據(jù)才會被清除,同時,如果瀏覽器支持,在瀏覽器崩潰并重啟之后仍然可以訪問存儲與sessionStorage中的數(shù)據(jù)

因為sessionStorage對象綁定于某個服務(wù)器會話,所以當(dāng)文件在本地運(yùn)行的時候是不可用的。

存儲在sessionStorage中的數(shù)據(jù)只能由最初給對象存儲數(shù)據(jù)的頁面訪問到,其只針對于當(dāng)前會話,所以對多頁面應(yīng)用有限制。

使用
sessionStorage對象是Storage的一個實例,所以可以使用setItem()或者直接設(shè)置新的屬性存儲數(shù)據(jù)
如:

// 使用方法存儲數(shù)據(jù)
sessionStorage.setItem('name', 'Hexon');
// 使用屬性存儲數(shù)據(jù)
sessionStorage.book = 'Professional Javascript'; 

// 使用方法讀取數(shù)據(jù)
var name = sessionStorage.getItem('name');
// 使用方法讀取數(shù)據(jù)
var book = sessionStorage.book;

// 通過key來迭代存儲與sessionStorage中的鍵值
for (var i = 0, len = sessionStorage.length; i < len; i++) {
  var key = sessionStorage.key(i);
  var value = sessionStorage.getItem(key);
  alert(key + '=' + value);
}

// 使用for-in循環(huán)迭代sessionStorage中的值
for (var key in sessionStorage) {
  val value = sessionstorage.getItem(key);
  alert(key + '=' + value);

不同的瀏覽器寫入數(shù)據(jù)方面略有不同,F(xiàn)ireFox和WebKit實現(xiàn)了同步寫入,所以添加到存儲空間中的數(shù)據(jù)是立刻被提交的。而IE的實現(xiàn)是異步寫入數(shù)據(jù),在設(shè)置數(shù)據(jù)和將數(shù)據(jù)寫入磁盤之間可能有延遲

總結(jié):sessionStorage對象應(yīng)該只用于針對會話小段數(shù)據(jù)存儲。如果需要跨會話存儲數(shù)據(jù),那么localStorage或者globalStorage更合適

globalStorage對象

只用FireFox2中實現(xiàn)了globalStorage對象,主要目的是為了實現(xiàn) 跨會話存儲數(shù)據(jù),但有特定的訪問限制。

要使用globalStorage,首先要指定哪些域名可以訪問該數(shù)據(jù)。

使用方法

// 只針對 域名 wrox.com 的存儲訪問
globalStorage['wrox.com'].name = 'hexon';
var name = globaleStorage['wrox.com'].name;

注意:

  • globalStorage對象不是Storage的實例,而具體的globalStorage['wrox.com'] 才是
  • 當(dāng)使用 globalStorage[''].name = 'hexon'來存儲數(shù)據(jù)時,表示任何人都可以訪問,一定不要這樣做,不安全
  • 對globalStorage空間的訪問,是依據(jù)發(fā)起請求的頁面的域名、協(xié)議和端口 來限制的;如使用https協(xié)議在wrox.com中存儲了數(shù)據(jù),那么通過http訪問的wrox.com的頁面將無法訪問該數(shù)據(jù)
  • 如果事先無法確定域名,那么使用 location.host 作為屬性名比較安全,表示頁面必須來自于同一個域名、協(xié)議和端口,才可以訪問
  • 如果不使用removeItem() 或者 delete 刪除,或者用戶未清除瀏覽器緩存,存儲在globalStorage屬性中的數(shù)據(jù)將會一直保存在磁盤上

注意: globalStorage對象在修訂過的HTML5規(guī)范中被localStorage對象所取代

localStorage 對象

localStorage對象在修訂過的HTML5規(guī)范中作為持久保存客戶端數(shù)據(jù)的方案取代了globalStorage。

與globalStorage不同,不能給localStorage指定規(guī)則,規(guī)則在HTML5規(guī)范中就被制定,要訪問同一個localStorage對象,頁面必須來自同一個域名(子域名無效)、同一種協(xié)議,在同一端口上,這相當(dāng)于 globalStorage[location.host];

localStorage是Storage類型的實例,因此可以像使用sessionStorage一樣使用它

同時, 為了兼容只支持globalStorage對象的瀏覽器,可以使用以下方式進(jìn)行能力檢測:

function getLocalStorage() {
  if (tpyeof localStorage === 'object') {
     return localStorage;
  } else if (typeof globalStorage === 'object') {
     return globalStorage[location.host];
  }  else {
     throw new Error('Local Storage not available.');
  }
}

sessionStorage和localStorage的對比與使用

概念

這兩者都是本地存儲,均不會被發(fā)送到服務(wù)器端,其主要在生命周期上有比較明顯的區(qū)別;localStorage的生命周期更長,沒有過期時間,原則上要等到通過JavaScript將內(nèi)容清除掉或者清空cookie時才會消失;而sessionStorage則在Browser或Tab被關(guān)閉時就會清空

限制

  • 對于localStorage而言,大多數(shù)桌面瀏覽器會設(shè)置每個來源5MB的限制,具體依瀏覽器而異
  • 對于sessionStorage,也因瀏覽器而異,一般每個來源在2.5MB ~ 5MB 之間

瀏覽器支持情況
這兩者都都需要瀏覽器的API支持,瀏覽器的支持情況如下:

image.png

使用
通過window.localStoragewindow.sessionStorage這而兩個對象進(jìn)行操作

以操作localStorage為例:

  • 從存儲中獲取值
    window.localStorage.getItem('key')
function setStyles() {
  var currentColor = localStorage.getItem('bgcolor');
  var currentFont = localStorage.getItem('font');
  var currentImage = localStorage.getItem('image');

  document.getElementById('bgcolor').value = currentColor;
  document.getElementById('font').value = currentFont;
  document.getElementById('image').value = currentImage;

  htmlElem.style.backgroundColor = '#' + currentColor;
  pElem.style.fontFamily = currentFont;
  imgElem.setAttribute('src', currentImage);
}
  • 在存儲中設(shè)置值
    window.localStorage.setItem可以從存儲中獲取指定的數(shù)據(jù)項或者設(shè)置新的數(shù)據(jù)項,該方法接受兩個參數(shù)——要創(chuàng)建/修改的數(shù)據(jù)項的鍵,和對應(yīng)的值。
function populateStorage() {
  localStorage.setItem('bgcolor', document.getElementById('bgcolor').value);
  localStorage.setItem('font', document.getElementById('font').value);
  localStorage.setItem('image', document.getElementById('image').value);
  setStyles();
}
  • 通過 StorageEvent 響應(yīng)存儲的變化
    無論何時,storage對象發(fā)生變化時(即創(chuàng)建/更新/刪除,重復(fù)設(shè)置相同的項不會觸發(fā),storage.clear()方法至多觸發(fā)一次),都會觸發(fā)StorageEvent事件
    window.addEventListener('storage', function(){});
    示例:
window.addEventListener('storage', function(e) {  
  document.querySelector('.my-key').textContent = e.key;
  document.querySelector('.my-old').textContent = e.oldValue;
  document.querySelector('.my-new').textContent = e.newValue;
  document.querySelector('.my-url').textContent = e.url;
  document.querySelector('.my-storage').textContent = e.storageArea;
});

注意:在同一個頁面內(nèi)發(fā)生的改變不會起作用——在相同域名下的其他頁面(如一個新標(biāo)簽或 iframe)發(fā)生的改變才會起作用。在其他域名下的頁面不能訪問相同的 Storage 對象。

  • 刪除數(shù)據(jù)記錄
    window.localStorage.removeItem():接收一個參數(shù),要刪除的數(shù)據(jù)項key值
    window.localStorage.clear():不接收參數(shù),只是簡單的清空域名對應(yīng)的整個存儲數(shù)據(jù)

cookie

起源: 最初由網(wǎng)景公司引入,用于在客戶端存儲回話信息

工作方式:要求服務(wù)器對任意HTTP請求,在響應(yīng)頭中添加Set-Cookie 字段來設(shè)置cookie,在客戶端接收到這個cookie信息之后,將其存儲起來,在此之后,當(dāng)客戶端再給創(chuàng)建它的域名發(fā)送HTTP請求時,都會在HTTP頭中添加cookie信息,服務(wù)器可以根據(jù)這個cookie信息來決定該用戶可以執(zhí)行哪些操作(例如:是否允許它進(jìn)行訪問)
,
cookie的組成:
cookie由瀏覽器保存在客戶端計算機(jī)中,由以下幾塊信息組成:

  • 名稱:cookie的名稱,這是唯一的,且字符不區(qū)分大小寫。注意:cookie的名稱必須是經(jīng)過URL編碼的
  • :存儲在cookie中的字符串值。注意:值必須經(jīng)過URL編碼
  • :cookie對于哪個域有效,所有向該域發(fā)送的請求中,都會包含這個cookie信息,如果沒有設(shè)置,則這個域會被認(rèn)作是設(shè)置cookie的那個域
  • 路徑:對于域下的路徑訪問,會包含cookie信息
  • 失效時間
  • 安全標(biāo)志

一個服務(wù)器發(fā)給客戶端的SetCookie信息,如下:

HTTP/1.1 200 OK
Content-type: text/html
Set-cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com; path=/; secure
Other-header: other-header-value

Set-cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT domain=.wrox.com; path=/; secure
這個Set-cookie的解釋如下:

  • cookie名稱: name
  • cookie的值:value (注意:值跟名稱是不同的東西)
  • 失效時間:Mon, 22-Jan-07 07:10:24 GMT;(這是GMT時間)
  • 域名: .wrox.com
  • 路徑: /
  • 安全標(biāo)志: secure(只有當(dāng)客戶端通過SSH連接時,才可以傳輸該cookie)

cookie的特點(diǎn)

  • 創(chuàng)建方式:是由服務(wù)器來創(chuàng)建 cookie 信息的
  • 存放位置:客戶端接收到服務(wù)器的cookie信息之后,將其存放在客戶端的計算機(jī)中
  • cookie個數(shù)限制:cookie是綁定在域名下的,因此每個域的cookie個數(shù)是有限的,不同瀏覽器的限制不同,一般為50個,chrome和safari沒有硬性限制。
  • cookie尺寸限制:對于每個域下的cookie的尺寸限制為4K字節(jié),注意:是一個域下的所有cookie的總尺寸之和要小于4K字節(jié),不是單個cookie的尺寸
  • 失效時間:默認(rèn)情況下,瀏覽器會話結(jié)束時即將所有的cookie刪除,但是,可以自己設(shè)置失效時間,當(dāng)未到達(dá)失效時間時,cookie將一直保存在客戶端計算機(jī)中,除非自己手動刪除
  • cookie會被附加在每個http請求中,因此會增加流量
  • 安全標(biāo)志:當(dāng)指定后(通過Set-Cookie中添加 secure 關(guān)鍵字即可),cookie只有在使用SSL連接的時候才發(fā)送到服務(wù)器

注意事項

  • cookie個數(shù)和尺寸的限制,超過限制后,不同的瀏覽器有不同的處理方式,因此,一定不要超過限制
  • 域、路徑、失效時間和secure標(biāo)志都是服務(wù)器給瀏覽器的指示,以指定何時應(yīng)該發(fā)送cookie,這些參數(shù)不會作為發(fā)送給服務(wù)器cookie信息的一部分
  • cookie的名稱是經(jīng)過URL編碼的,注意:是名稱
  • Javascipt中處理cookie有些復(fù)雜,主要是接口不好用,即:document.cookie

cookie的缺陷

  • cookie會被附加在每個http請求中,因此會無形中增加流量
  • 由于http請求中的cookie是明文傳輸,因此有安全問題(除非使用https),不要使用cookie存放重要的數(shù)據(jù)
  • cookie的大小限制是4kb,對于復(fù)雜的存儲需求可能不夠用

cookie的使用

  • 獲取cookie:document.cookie,通過該方法可以獲取cookie
  • 刪除cookie:設(shè)置document.cookie并不會覆蓋cookie,除非設(shè)置的cookie的名稱已經(jīng)存在。那么就會對原cookie進(jìn)行覆蓋
    封裝的cookie代碼
let CookieUtil = {
    get: (name) => {
      let cookieName = encodeURIComponent(name) + "=",
          cookieStart = document.cookie.indexOf(cookieName),
          cookieValue = null;

      if (cookieStart > -1) {
        let cookieEnd = document.cookie.indexOf(';', cookieStart);
        if (cookieEnd === -1) {
          cookieEnd = document.cookie.length;
        }
        cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
      }

      return cookieValue;
    },
    set: function (name, value, expires, path, domain, secure) {
      let cookieText = encodeURIComponent(name) + '=' +
                       encodeURIComponent(value);

      if (expires instanceof Date) {
        cookieText += '; expires=' + expires.toGMTString();
      }

      if (path) {
        cookieText += '; path=' + path;
      }

      if (domain) {
        cookieText += '; domain=' + domain;
      }

      if (secure) {
        cookieText += '; secure';
      }

      document.cookie = cookieText;
    },

    // 刪除cookie, 并沒有直接的刪除cookie的方法,這里通過重新設(shè)置cookie名稱,來對cookie進(jìn)行替換
    // 同時 將過期時間expires設(shè)置為過去的時間,
    unset: function(name, path, domain, secure) {
      this.set(name, '', new Date(0), path, domain, secure);
    }
  }

瀏覽器本地存儲中 cookie 和 localStorage 有什么區(qū)別? localStorage 如何存儲刪除數(shù)據(jù)。

sessionStorage、localStorage和cookie 這三者都是用于瀏覽器端存儲數(shù)據(jù),而且都是字符串類型的鍵值對。

區(qū)別在于:

  • 數(shù)據(jù)傳輸方面:在每個http請求中都會附加cookie信息,cookie中的信息能夠被推送到服務(wù)器端;而sessionStorage和localStorage不會被推送到服務(wù)器端
  • 存儲大小不同:cookie最大支持4KB,而sessionStorage和localStorage一般在2.5~10MB
  • 生命周期:默認(rèn)情況下,cookie開始于瀏覽器啟動,結(jié)束于瀏覽器關(guān)閉,但是可以手動設(shè)置cookie的過期時間,同時,到期后被刪除;而對于localStorage,沒有過期時間,原則上只要不手動刪除,其會一直被保存在本地上,sessionStorage的數(shù)據(jù)關(guān)閉瀏覽器時清除
  • 被創(chuàng)造的初衷不同:sessionStorage和localStorage都屬于WebStorage,創(chuàng)建他們的目的就是用于存儲客戶端數(shù)據(jù);
    而cookie最早在網(wǎng)景的瀏覽器中被支持,主要目的是為了辨別用戶身份而存儲在本地終端的數(shù)據(jù)。

參考:在HTML5的時代,重新認(rèn)識Cookie


參考:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容