除了名(name)和值(value),cookie还有一些可选的属性来控制cookie的有效期和作用域。cookie默认的有效期很短暂,它只能持续在Web浏览器的会话期间(不是服务器端的会话,浏览器端的会话关闭浏览器就结束),一旦用户关闭浏览器,cookie保存的数据就丢失了。这和sessionStorage的有效期还是有区别的,sessionStorage理论上有效期更短一些,它关联的是单个窗口,cookie关联的是浏览器。
cookie的作用域是通过文档源和文档路径来确定的。cookie中的domain字段指定cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息,这个值可以包含子域(如www.xx.com),也可以不包含它(如xx.com,则对xx.com的所有子域名都有效)。如果没有明确规定,那么这个域会被认做来自设置cookie那个域。
对于指定域中的路径(path字段也只能设置为指定域中的路径),浏览器会向服务器发送cookie。比如你可以指定cookie只有从http: //www.xx.com/me/才能访问,那么http://www.xx.com的页面就不会发送该cookie信息,这是path字段的作用
保存cookie
最简单的保存是使用以下代码
document.cookie = 'version=' + encodeURIComponent(document.lastModified);
由于cookie的值不许包含分号,逗号和空白符,因此存储之前一般可以用encodeURIComponent对值进行编码(不是用来加密), 相应的,读取cookie值的时候需要采用decodeURIComponent()函数解码。
如果想延长cookie的有效期(而不是默认的关闭浏览器就过期),可以设置max-age属性来指定cookie的有效期。
function setcookie(name, value, daysToLive){
var cookie = name + '=' + encodeURIComponent(value);
if(typeof daysToLive === 'number'){
cookie += ';max-age=' + (daysToLive * 60 * 60 * 24);
}
//不需要关心cookie中是否有已经有这个key,如果已经有这个key,会自动更新
document.cookie = cookie;
}
同样,如果要设置cookie的path,domain和secure属性,只需要在存储cookie值之前,以如下字符串形式追加在cookie之后:
;path=path
;domain=domain
;secure=secure
要改变cookie的值,需要使用相同的名字,路径和域,新的值重新设置cookie的值。要删除一个cookie,需要使用相同的名字,路径和域,然后指定一个任意(非空)的值,并且将max-age属性指定为0,再次设置cookie。
读取cookie
同源策略保证了只有允许的访问者可以读取cookie。
通过document.cookie属性可以获取cookie的值,取出来的cookie不同名/值对之间通过分号和空格隔开(注意多了一个空格)。为了更好地查看cookie的值,一般会采用split()方法将cookie值中的名/值对都分离出来。
我们实现一个cookieStorage函数,这样我们就可以像使用localStorage一样来使用这个对象了,但是以下代码没有实现存储事件
function cookieStorage(maxage, path){
//获取一个存储全部cookie信息的对象
//维护这样一个对象就不需要重复去取cookie
var cookie = (function(){
var cookie = {};
var all = document.cookie;
//如果为空的话返回一个空对象
if(all === '') return cookie;
var list = all.split('; ');
for(var i = 0; i < list.length; i++){
var cookie = list[i];
var p = cookie.indexOf('=');
var name = cookie.substring(0, p);
var value = cookie.substring(p + 1);
value = decodeURIComponent(value);
cookie[name] = value
}
return cookie;
})()
//将所有cookie的名字存储到数组中
var keys = [];
for(var key in cookie) keys.push(key);
this.length = keys.length;
//返回第n个cookie的名字,如果n越界则返回null
this.key = function(n){
if(n < 0 || n > keys.length) return null;
//没必要再写一个else
return keys[n];
}
//返回指定名字的cookie值,如果不存在则返回null
this.getItem = function(name){
return cookie[name] || null;
}
//存储cookie值
this.setItem = function(key, value){
if(!(key in cookie)){
keys.push(key);
this.length++;
}
//如果存在相同的key,则更新value
cookie[key] = value;
var cookie = key + '=' + encodeURIComponent(value);
if(maxage) cookie += ';max-age=' + maxage;
if(path) cookie += ';path=' + path;
document.cookie = cookie;
}
//删除指定的cookie
this.removeItem = function(key){
if(!(key in cookie)) return;
//从内部维护的cookie中删除指定cookie
delete cookie[key];
for(var i = 0; i < keys.length; i++){
if(keys[i] == key){
//遍历数组,如果数组中有该元素,将数组中切去这个元素
keys.splice(i, 1);
break;
}
}
this.length--;
document.cookie = key + '=;max-age=0';
}
this.clear = function(){
for(var i = 0; i < keys.length; i++){
document.cookie = keys[i] + '=;max-age=0';
}
cookie = {};
keys = [];
this.length = 0;
}
}