大概是個人業務領域比較狹窄的緣由,我老是會據說cookie,卻不多在實際的開發中應用或者實踐過它,今天恰好看到<<JavaScript高級程序設計第三版>>的數據存儲部分,說到了cookie,這裏就對cookie作一個深刻訪談,但願和我同樣對cookie似曾相識的朋友能夠真正的熟悉cookie,並學會利用cookie來服務咱們的業務.^_^^_^前端
cookie,是服務器爲了辨別用戶身份,進行session跟蹤而存儲在用戶本地終端上的數據(一般通過加密).web
域名限制 數組
由於cookie通常用於與服務器進行交互,因此它通常存放在對應的域名下.當設定了一個cookie後,再給建立它的域名發送請求時,都會包含這個cookie,這個限制確保了儲存在cookie中的信息只能讓批准的接受者訪問,而沒法被其餘域訪問.瀏覽器
個數限制
因爲cooki是存儲在客戶端計算機上的,還加入了一些限制確保cookie不會被惡意使用,同時不會佔據太多磁盤空間.每一個域的cookie總數是有限的,不過瀏覽器之間各有不一樣.安全
當超過單個域名限制以後還要在設置cookie,瀏覽器會清除之前設置的cookie.IE和Opera會刪除最近最少使用過的cookie.因此考慮cookie限制很是重要,避免出現不可預期的後果.服務器
尺寸限制
瀏覽器中對於cookie的尺寸也有限制,大多數瀏覽器是4KB的長度限制,尺寸限制影響一個域下全部的cookie,而並不是每一個cookie單獨限制.
若是你嘗試建立查過最大限制的cookie,那麼該cookie會被悄無聲息地丟掉.cookie
cookie由瀏覽器保存的如下幾塊信息構成.session
注意發送cookie的時候只會發送cookie的名和值纔會被髮送,其餘值只會cookie信息的描述.dom
經常使用場景: cookie通常用來作登陸驗證,用戶登錄的時候講用戶名和密碼傳入到服務器端,服務器會返回將用戶相關的認證信息,而後由服務器將這些信息寫入cookie或者由前端使用js操做cookie將這些信息寫入到cookie中(若是服務器經過Set-Cookie的方式直接寫入則不須要前端的參與,前端是無感知的),登錄成功之後的用戶在該域名下的訪問都會在請求中發送cookie,做爲該用戶的身份標識.咱們這裏主要討論的是前端使用js操做cookie的狀況.函數
不經常使用場景: 咱們也能夠用js操做cookie,在cookie上存儲咱們臨時須要的用於頁面交互的變量,這個時候cookie就充當了sessionStorage或者localStorage的角色.
因爲JavaScript中讀寫cookie不是很是直觀,經常須要寫一些函數來簡化cookie的功能.基本的操做有三種: 讀取,寫入,刪除;
說明: 我不知道看這篇文章的朋友是否是瞭解這些操做cookie的方法,若是不瞭解,我建議你先想想,而後嘗試着本身去寫,而後感興趣的話再來看看個人代碼,也能夠分享到評論區,咱們一塊兒來看看這些實現方法的優劣,不知道不一樣思想的碰撞會不會擦出奇妙的火花呢? 很期待奧~
封裝的操做cookie的代碼以下:
const CookieUtil = { // 獲取cookie 接受的參數 cookie的名稱 get: function(name) { var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null; if(cookieStart !== -1) { var cookieEnd = document.cookie.indexOf(";",cookieStart); if(cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.LENGTH, cookieEnd)); } return cookieValue; }, // 設置cookie, 接收參數: cookie的名稱, cookie的值, // 可選的用於執行cookie什麼時候應被刪除的Date對象,cookie的可選的URL路徑, 可選的域和是否要添加secure標誌的布爾值 set: function (name, value, expires, path, domain, secure) { var 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的名稱,可選的路徑參數,可選的域參數和可選的安全參數 unset: function (name, path, domain, secure) { // 將某個cookie的過時時間早於當前時間,則會被馬上刪除,該方法設置失效時間爲1970年1月1日 this.set(name, "", new Date(0), path, domain, secure); } } // 設置cookie CookieUtil.set("name", "Nicholas"); CookieUtil.set("book", "Professional JavaScript"); // 讀取cookie的值 CookieUtil.get("name"); CookieUtil.get("book"); // 刪除cookie CookieUtil.unset("name"); CookieUtil.unset("book");
爲了繞開瀏覽器的單域名下的cookie數限制,一些開發人員使用了一種成爲子cookie的改變,子cookie是存放在單個cookie中的更小段的數據,一般是多個名稱值對的形式.子cookie對常見的格式以下所示:
namename1=value1&name2=value2&name3=value3&name4=value4&name5=value5
子cookie通常也以查詢字符串的格式進行格式化,而後這些值可使用單個cookie進行儲存和訪問,而非對每一個名稱-值對兒使用不一樣的cookie存儲,最後網站或者web應用程序能夠無需大到單域名cookie上限也能夠存儲更加結構化的數據.
爲了更好的操做子cookie,必須創建一系列新方法,子cookie的解析和序列化會因子cookie的指望用途而略有不一樣並更加複雜些,例如,要得到一個子cookie,首先要遵循與得到cookie同樣的基本步驟,可是在解碼cookie值以前,須要操做字符串,遍歷數組之類的操做來找出子cookie的信息.
說明: 我不知道看這篇文章的朋友是否是瞭解這些操做cookie的方法,若是不瞭解,我建議你先想想,而後嘗試着本身去寫,而後感興趣的話再來看看個人代碼,也能夠分享到評論區,咱們一塊兒來看看這些實現方法的優劣,不知道不一樣思想的碰撞會不會擦出奇妙的火花呢?
操做子cookie的方法以下:
// 操做子cookie的一組方法 var SubCookieUtil = { // 獲取cookie, 接收兩個參數,cookie名和子cookie名 // 若是不穿子cookie名,則是普通的獲取方法,若是傳了,則取對應子cookie名的value. get: function (name, subName) { var subCookies = this.getAll(name); if(subCookies) { return subCookies[subName]; } else { return null; } }, // 判斷若是cookie中name對應的value不包含子cookie, // 則返回解碼後的cookieValue,若是包含子cookie,則返回處理後的result對象 getAll: function (name) { var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieEnd, result={}, cookieValue= null, i,len,subCookies='', parts = []; if(cookieStart !== -1) { cookieEnd = document.cookie.indexOf(";", cookieStart); if(cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); if(cookieValue.length > 0) { if(cookieValue.indexOf("&") > -1) { subCookies = cookieValue.split("&"); console.log("get subCookies",subCookies); for(i = 0,len = subCookies.length; i < len; i++) { parts = subCookies[i].split("="); result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } } else { parts = cookieValue.split("="); result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]) } return result; } } return null; }, // 一樣的,要設置子cookie,也有新的set方法 set: function(name, subName, value, expires, path, domain, secure) { var subCookies = this.getAll(name) || {}; subCookies[subName] = value; this.setAll(name, subCookies, expires, path, domain, secure); }, setAll: function(name, subCookies, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=", subCookieParts = [], sub, result; // 將subCookies對象裏的cookie值對編碼,並放進subCookieParts數組中 for(sub in subCookies) { if(subCookies.hasOwnProperty(sub)) { subCookieParts.push(encodeURIComponent(sub)+ "=" + encodeURIComponent(subCookies[sub])); } } if(subCookieParts.length > 0) { cookieText += subCookieParts.join("&"); if(expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } } else { cookieText += "; expires=" + (new Date(0)).toGMTString(); } if(path) { cookieText += "; path=" + path; } if(domain) { cookieText += "; domain=" + domain; } if(secure) { cookieText += "; secure"; } document.cookie = cookieText; }, // 刪除cookie 刪除單個cookie unset: function(name, subName, path, domain, secure) { var subCookies = this.getAll(name); subCookies[subName] ? delete subCookies[subName] : ''; this.setAll(name, subCookies, null, path, domain, secure); }, //刪除cookie 刪除多個cookie unsetAll: function (name, path, domain, secure) { this.setAll(name, null, new Date(0), path, domain, secure); } } // 假設 document.cookie = "data=name=Nicholas&book=Professional%20JavaScript" // 設置兩個cookie SubCookieUtil.set("xiaosisi", "name", "Nicholas"); SubCookieUtil.set("xiaosisi", "book", "Professional JavaScript"); SubCookieUtil.set("xiaosisi", "sisisi", "撕撕撕"); // 設置所有子cookie和失效日期 SubCookieUtil.setAll("xiaosisi", {name: "Nicholas", book:"Professional JavaScript", sisisi: "撕撕撕"}, new Date("2018-10-25")); // 修更名字的值,並修改失效日期 SubCookieUtil.setAll("xiaosisi", "name", "MIrascl", new Date("2018-11-25")); // 刪除名爲sisisi的子cookie SubCookieUtil.unset("xiaosisi", "sisisi"); // 刪除整個cookie SubCookieUtil.unsetAll("xiaosisi");
關於cookie有兩點須要注意的地方:
第一: 因爲全部的cookie都會由瀏覽器做爲請求頭髮送,因此在cookie中存儲大量信息會影響到特定域的請求性能,cookie信息越大,完成對服務器請求的時間也就越長.儘管瀏覽器對cookie的大作了限制,不過最好仍是儘量在cookie中少存儲信息,以避免影響性能.
第二:必定不要在cookie中存儲重要和敏感的數據.cookie的存儲不是很安全,其中包含的任何數據均可以被他人訪問,重要的用戶信息不建議存儲在cookie裏.
若是讀者們有關於cookie的比較好的使用策略歡迎在評論區留言或者私信我奧~共同進步是最讓人開心的事兒呢~~~