JavaScript學(xué)習(xí)筆記整理(12):客戶端存儲

2018-06-19 12:02 更新
      Web應(yīng)用允許使用瀏覽器提供的API實現(xiàn)將數(shù)據(jù)存儲到用戶的電腦上。

一、localStorage和sessionStorage

localStorage和sessionStorage這兩個屬性都代表同一個Storage對象(一個持久化關(guān)聯(lián)數(shù)組,數(shù)組使用字符串來索引,存儲的值都是字符串形式的)。

1.1 存儲有效期和作用域
localStorage和sessionStorage的區(qū)別在于存儲的有效期和作用域的不同。

1.1.1 localStorage
通過localStorage存儲的數(shù)據(jù)是永久性的,除非Web應(yīng)用刻意刪除存儲的數(shù)據(jù)或用戶通過設(shè)置瀏覽器設(shè)置來刪除,否則數(shù)據(jù)將一直保留在用戶的電腦里,永不過期。

localStorage的作用域是限定在文檔源(document origin)級別。

同源的文檔間共享同樣的localStorage數(shù)據(jù)。

1.1.2 sessionStorage
sessionStorage的作用域同樣是限定在文檔源中,不過它被限定在窗口中。也就是說,如果同源的文檔在不同的瀏覽器標(biāo)簽頁中,那它們互相之間擁有的是各自的sessionStorage數(shù)據(jù),無法共享。

注意:基于窗口作用域的sessionStorage指的窗口只是頂級窗口。如果一個瀏覽器標(biāo)簽頁包含多個<iframe>元素,它們包含的文檔是同源的,兩者之間的sessionStorage是可共享的。

1.2 存儲API
我們可以將localStorage和sessionStorage當(dāng)做普通的JavaScript對象:通過設(shè)置屬性來存儲字符串值,查詢該屬性來讀取該值。

localStorage.user = 'TG';

當(dāng)然,這兩個對象也提供了對應(yīng)的存儲和讀取的方法。

localStorage.setItem('user','TG');   //存儲一個以“user”的名字存儲的數(shù)值。


localStorage.getItem('user');  //讀取

同樣,sessionStorage也有這兩個方法。

sessionStorage.setItem('user','TG');

sessiontStorage.getItem('user');

還可以使用removeItem()和clear()方法來刪除。

localStorage.removeItem('user');  //刪除名為“user”的數(shù)據(jù)。

localStorage.clear();  //刪除所有存儲的數(shù)據(jù)


sessionStorage.removeItem('user');

sessionStorage.clear();

遍歷存儲數(shù)據(jù)。

for(var i=0; i < localStorage.length; i++){

  var name = localStorage.key(i);  //獲取第i對的名字

  console.log(localStorage.getItem(name); //獲取該對的值

}

其中的key方法,根據(jù)位置(從0開始)獲得鍵值。

localStorage.key(1);


1.3 storage事件

當(dāng)儲存的數(shù)據(jù)發(fā)生變化時,會觸發(fā)storage事件。我們可以指定這個事件的回調(diào)函數(shù)。

window.addEventListener("storage",onStorageChange);

回調(diào)函數(shù)接受一個event對象作為參數(shù)。這個event對象的key屬性,保存發(fā)生變化的鍵名。

function onStorageChange(e) {   

  console.log(e.key);      

}

除了key屬性,event對象的屬性還有三個:

oldValue:更新前的值。如果該鍵為新增加,則這個屬性為null。  

newValue:更新后的值。如果該鍵被刪除,則這個屬性為null。  

url:原始觸發(fā)storage事件的那個網(wǎng)頁的網(wǎng)址。

值得特別注意的是,該事件不在導(dǎo)致數(shù)據(jù)變化的當(dāng)前頁面觸發(fā)。如果瀏覽器同時打開一個域名下面的多個頁面,當(dāng)其中的一個頁面改變sessionStorage或localStorage的數(shù)據(jù)時,其他所有頁面的storage事件會被觸發(fā),而原始頁面并不觸發(fā)storage事件。可以通過這種機制,實現(xiàn)多個窗口之間的通信。所有瀏覽器之中,只有IE瀏覽器除外,它會在所有頁面觸發(fā)storage事件。


二、cookie

cookie是指Web瀏覽器存儲的少量數(shù)據(jù),每個Cookie的大小一般不能超過4KB。


Cookie保存以下幾方面的信息。

Cookie的名字  

Cookie的值  

到期時間  

所屬域名(默認(rèn)是當(dāng)前域名)  

生效的路徑(默認(rèn)是當(dāng)前網(wǎng)址)


我們可以通過特殊的格式的字符串形式來讀寫Document對象的cookie屬性。

document.cookie  //讀取當(dāng)前頁面的所有cookie


我們可以通過檢查navigator.cookieEnabled屬性來檢測當(dāng)前cookie是否啟用。若值為true,表示cookie是啟用的。


2.1 cookie屬性:有效期和作用域

cookie默認(rèn)的有效期很短暫,它只能持續(xù)在Web瀏覽器的會話期間,一旦用戶關(guān)閉瀏覽器,cookie保存的數(shù)據(jù)就會丟失。


注意:cookie的有效期和sessionStorage的有效期是有區(qū)別的:cookie的作用域并不是局限在瀏覽器的單個窗口中,它的有效期和整個瀏覽器進程而不是單個瀏覽器窗口的有效期一致。


cookie的作用域是通過文檔源和文檔路徑來確定的。


2.2 保存cookie

document.cookie屬性是可寫的,可以通過它為當(dāng)前網(wǎng)站添加Cookie。

document.cookie = 'user=TG';

Cookie的值必須寫成key=value的形式。注意,等號兩邊不能有空格。另外,寫入Cookie的時候,必須對分號、逗號和空格進行轉(zhuǎn)義(它們都不允許作為Cookie的值),這可以用encodeURIComponent方法進行編碼,讀取時再采用decodeURIComponent方法解碼。


但是,document.cookie一次只能寫入一個Cookie,而且寫入并不是覆蓋,而是添加。

document.cookie = 'test1=hello';  

document.cookie = 'test2=world';  

document.cookie  

// test1=hello; test2=world

如果要延長cookie的有效期,就需要設(shè)置mav-age屬性來指定cookie的有效期(單位是秒)

document.cookie = 'user=TG;max-age=60*60*24';  //將有效期設(shè)置為一天

2.3 讀取cookie

使用JavaScript表達式來讀取cookie屬性時,其返回的值是一個字符串,該字符串都是由一系列名/值對組成,不同名/值對之間通過“分號和空格”分開,其內(nèi)容包含了所有作用在當(dāng)前文檔的cookie。

一般情況下,我們會采用split()方法將cookie值中的名/值對都分離出來。當(dāng)然,如果之前進行了一系列的編碼,就需要先解碼再分離。

function getCookie(cname)  

{  

  var name = cname + "=";  

  var ca = document.cookie.split(';');  

  for(var i=0; i<ca.length; i++)    

  {   

    var c = ca[i].trim();   

    if (c.indexOf(name)==0) 

    {

      return c.substring(name.length,c.length); 

    }  

  }  

  return "";  

}


2.4 其他屬性

除了Cookie本身的內(nèi)容,還有一些可選的屬性也是可以寫入的,它們都必須以分號開頭。

Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]

上面的Set-Cookie字段,用分號分隔多個屬性: 

(1)value屬性 

value屬性是必需的,它是一個鍵值對,用于指定Cookie的值。

 

(2)expires屬性 

expires屬性用于指定Cookie過期時間。它的格式采用Date.toUTCString()的格式。 

expires=Thu, 01 Jan 1970 00:00:00 GMT

如果不設(shè)置該屬性,或者設(shè)為null,Cookie只在當(dāng)前會話(session)有效,瀏覽器窗口一旦關(guān)閉,當(dāng)前Session結(jié)束,該Cookie就會被刪除。 

瀏覽器根據(jù)本地時間,決定Cookie是否過期,由于本地時間是不精確的,所以沒有辦法保證Cookie一定會在服務(wù)器指定的時間過期。 


(3)domain屬性 

domain屬性指定Cookie所在的域名,比如example.com或.example.com(這種寫法將對所有子域名生效)、subdomain.example.com。 

如果未指定,默認(rèn)為設(shè)定該Cookie的域名。所指定的域名必須是當(dāng)前發(fā)送Cookie的域名的一部分,比如當(dāng)前訪問的域名是example.com,就不能將其設(shè)為google.com。只有訪問的域名匹配domain屬性,Cookie才會發(fā)送到服務(wù)器。 


(4)path屬性 

path屬性用來指定路徑,必須是絕對路徑(比如/、/mydir),如果未指定,默認(rèn)為請求該Cookie的網(wǎng)頁路徑。 

只有path屬性匹配向服務(wù)器發(fā)送的路徑,Cookie才會發(fā)送。這里的匹配不是絕對匹配,而是從根路徑開始,只要path屬性匹配發(fā)送路徑的一部分,就可以發(fā)送。比如,path屬性等于/blog,則發(fā)送路徑是/blog或者/blogroll,Cookie都會發(fā)送。path屬性生效的前提是domain屬性匹配。 


(5)secure 

secure屬性用來指定Cookie只能在加密協(xié)議HTTPS下發(fā)送到服務(wù)器。 

該屬性只是一個開關(guān),不需要指定值。如果通信是HTTPS協(xié)議,該開關(guān)自動打開。 


(6)max-age 

max-age屬性用來指定Cookie有效期,比如60 * 60 * 24 * 365(即一年31536e3秒)。


2.5 cookie的限制

瀏覽器對Cookie數(shù)量的限制,規(guī)定不一樣。目前,F(xiàn)irefox是每個域名最多設(shè)置50個Cookie,而Safari和Chrome沒有域名數(shù)量的限制。 


所有Cookie的累加長度限制為4KB。超過這個長度的Cookie,將被忽略,不會被設(shè)置。


由于Cookie可能存在數(shù)量限制,有時為了規(guī)避限制,可以將cookie設(shè)置成下面的形式。

name=a=b&c=d&e=f&g=h

上面代碼實際上是設(shè)置了一個Cookie,但是這個Cookie內(nèi)部使用&符號,設(shè)置了多部分的內(nèi)容。因此,讀取這個Cookie的時候,就要自行解析,得到多個鍵值對。這樣就規(guī)避了cookie的數(shù)量限制。


3、同源策略

瀏覽器的同源政策規(guī)定,兩個網(wǎng)址只要域名相同和端口相同,就可以共享Cookie。 


注意:這里不要求協(xié)議相同。也就是說,http://example.com設(shè)置的Cookie,可以被https://example.com讀取。



以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號