let CookieUtil = { get: function (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; }, unset: function (name, path, domain, secure){ this.set(name, "", new Date(0), path, domain, secure); } };
CookieUtil.get() 方法根據 cookie 的名字獲取相應的值。它會在 document.cookie 字符串中查找 cookie 名加上等於號的位置。若是找到了,那麼使用 indexOf() 查找該位置以後的第一個分號(表示了該 cookie 的結束位置)。若是沒有找到分號,則表示該 cookie 是字符串中的最後一個,則餘下的字符串都是 cookie 的值。該值使用 decodeURIComponent() 進行解碼並最後返回。若是沒有發現 cookie,則返回 null 。數組
CookieUtil.set() 方法在頁面上設置一個 cookie,接收以下幾個參數:cookie的名稱,cookie的值,可選的用於指定 cookie什麼時候應被刪除的 Date 對象,cookie的可選的 URL路徑,可選的域,以及可選的表示是否要添加 secure 標誌的布爾值。參數是按照它們的使用頻率排列的,只有頭兩個是必需的。在這個方法中,名稱和值都使用 encodeURIComponent() 進行了URL編碼,並檢查其餘選項。若是 expires參數是 Date 對象,那麼會使用 Date 對象的 toGMTString() 方法正確格式化 Date 對象,並添加到expires 選項上。方法的其餘部分就是構造 cookie字符串並將其設置到 document.cookie 中。沒有刪除已有 cookie 的直接方法。因此,須要使用相同的路徑、域和安全選項再次設置 cookie,並將失效時間設置爲過去的時間。瀏覽器
CookieUtil.unset() 方法能夠處理這種事情。它接收 4 個參數:要刪除的 cookie 的名稱、可選的路徑參數、可選的域參數和可選的安全參數。這些參數加上空字符串並設置失效時間爲 1970 年 1 月 1 日(初始化爲 0ms的 Date 對象的值),傳給 CookieUtil.set() 。這樣就能確保刪除 cookie安全
//設置 cookie CookieUtil.set("name", "Nicholas"); CookieUtil.set("book", "Professional JavaScript"); //讀取 cookie 的值 alert(CookieUtil.get("name")); //"Nicholas" alert(CookieUtil.get("book")); //"Professional JavaScript" //刪除 cookie CookieUtil.unset("name"); CookieUtil.unset("book"); //設置 cookie,包括它的路徑、域、失效日期 CookieUtil.set("name", "Nicholas", "/books/projs/", "www.wrox.com", new Date("January 1, 2010")); //刪除剛剛設置的 cookie CookieUtil.unset("name", "/books/projs/", "www.wrox.com"); //設置安全的 cookie CookieUtil.set("name", "Nicholas", null, null, null, true);
爲了繞開瀏覽器的單域名下的 cookie 數限制,一些開發人員使用了一種稱爲子 cookie(subcookie)的概念。子 cookie 是存放在單個 cookie 中的更小段的數據。也就是使用 cookie 值來存儲多個名稱值對。子 cookie 最多見的的格式以下所示:cookie
name=value&name1=value1&name2=value2&name3=value3&name4=value4&name5=value5
子 cookie 通常也以查詢字符串的格式進行格式化。而後這些值可使用單個 cookie 進行存儲和訪問,而非對每一個名稱鍵值對兒使用不一樣的 cookie 存儲。最後網站或者 Web 應用程序能夠無需達到單域名cookie 上限也能夠存儲更加結構化的數據。dom
爲了更好地操做子 cookie,必須創建一系列新方法。子 cookie 的解析和序列化會因子 cookie 的指望用途而略有不一樣並更加複雜些。例如,要得到一個子 cookie,首先要遵循與得到 cookie 同樣的基本步驟,可是在解碼 cookie 值以前,須要按以下方法找出子 cookie 的信息。函數
let SubCookieUtil = { get: function (name, subName){ let subCookies = this.getAll(name); if (subCookies){ return subCookies[subName]; } else { return null; } }, getAll: function(name){ let cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null, cookieEnd, subCookies, i, parts, result = {}; 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){ subCookies = cookieValue.split("&"); for (i=0, len=subCookies.length; i < len; i++){ parts = subCookies[i].split("="); result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } return result; } } return null; }, set: function (name, subName, value, expires, path, domain, secure) { let subcookies = this.getAll(name) || {}; subcookies[subName] = value; this.setAll(name, subcookies, expires, path, domain, secure); }, setAll: function(name, subcookies, expires, path, domain, secure){ let cookieText = encodeURIComponent(name) + "=", subcookieParts = new Array(), subName; for (subName in subcookies){ if (subName.length > 0 && subcookies.hasOwnProperty(subName)){ subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName])); } } if (cookieParts.length > 0){ cookieText += subcookieParts.join("&"); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; path=" + path; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } } else { cookieText += "; expires=" + (new Date(0)).toGMTString(); } document.cookie = cookieText; }, unset: function (name, subName, path, domain, secure){ let subcookies = this.getAll(name); if (subcookies){ delete subcookies[subName]; this.setAll(name, subcookies, null, path, domain, secure); } }, unsetAll: function(name, path, domain, secure){ this.setAll(name, null, new Date(0), path, domain, secure); } };
和set()及setAll() 同樣,路徑、域和 secure 標誌必須和以前建立的 cookie 包含的內容一致。針對整個 cookie 的失效日期則能夠在任何一個單獨的子cookie寫入的時候同時設置。工具
SubCookieUtil.getAll() 方法和 CookieUtil.get() 在解析 cookie 值的方式上很是類似。區別在於 cookie 的值並不是當即解碼,而是先根據 & 字符將子 cookie 分割出來放在一個數組中,每個子 cookie再根據等於號分割,這樣在 parts 數組中的前一部分即是子 cookie 名,後一部分則是子 cookie的值。這兩個項目都要使用 decodeURIComponent() 來解碼,而後放入 result 對象中,最後做爲方法的返回值。若是 cookie 不存在,則返回 null 。網站
//假設 document.cookie=data=name=Nicholas&book=Professional%20JavaScript //取得所有子 cookie var data = SubCookieUtil.getAll("data"); alert(data.name); //"Nicholas" alert(data.book); //"Professional JavaScript" //逐個獲取子 cookie alert(SubCookieUtil.get("data", "name")); //"Nicholas" alert(SubCookieUtil.get("data", "book")); //"Professional JavaScript" //設置兩個 cookie SubCookieUtil.set("data", "name", "Nicholas"); SubCookieUtil.set("data", "book", "Professional JavaScript"); //設置所有子 cookie 和失效日期 SubCookieUtil.setAll("data", { name: "Nicholas", book: "Professional JavaScript" }, new Date("January 1, 2010")); //修更名字的值,並修改 cookie 的失效日期 SubCookieUtil.set("data", "name", "Michael", new Date("February 1, 2010")); //僅刪除名爲 name 的子 cookie SubCookieUtil.unset("data", "name"); //刪除整個 cookie SubCookieUtil.unsetAll("data");