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");