本文深入解析 JavaScript 中 Cookie 作为全局变量存储机制的原理与应用。详细阐述 Cookie 的设置、读取、过期时间控制及路径域名限制,分析其安全性与局限性,并提供一套完整的通用 Cookie 处理函数封装方案,涵盖添加、获取与删除功能,帮助开发者高效管理 Web 客户端状态。
JavaScript Cookie 机制概述
JavaScript 提供了另一种机制来实现真正的全局变量,那就是 Cookie。Cookie 并非 JavaScript 语言本身的特性,而是浏览器提供的一种机制,它通过 document 对象的 cookie 属性暴露给 JavaScript 脚本,从而允许 JS 对其进行控制。
Cookie 概述
在前面的章节中,曾利用不变的框架来存储购物车数据,尽管商品显示页面不断变化,这种方式能模拟全局变量,但存在缺陷。例如,在导航框架内右键点击【刷新】,所有 JavaScript 变量都会丢失。因此,要实现严格的跨页面全局变量,这种方式不可行,而 Cookie 机制则能达成真正的目标。
Cookie 是浏览器提供的一种机制,它将 document 对象的 cookie 属性提供给 JavaScript。可以由 JavaScript 对其进行控制,而并不是 JavaScript 本身的性质。Cookie 是存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个 Cookie 可用。因此,Cookie 可以跨越一个域名下的多个网页,但不能跨越多个域名使用。
不同浏览器对 Cookie 的实现方式各异,但其本质相同。例如在 Windows 2000 以及 Windows xp 中,Cookie 文件存储于 documents and settings\userName\cookie\文件夹下。通常的命名格式为:userName@domain.txt。
Cookie 机制将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点。它可以用于以下几种场合。
(1)保存用户登录状态。例如将用户 id 存储于一个 Cookie 内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。Cookie 还可以设置过期时间,当超过时间期限后,Cookie 就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个月、一年等。
(2)跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是繁琐的,当利用了 Cookie 后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便。
(3)定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用 Cookie 来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。
(4)创建购物车。正如在前面的例子中使用 Cookie 来记录用户需要购买的商品一样,在结账的时候可以统一提交。例如淘宝网就使用 Cookie 记录了用户曾经浏览过的商品,方便随时进行比较。
当然,上述应用仅仅是 Cookie 能完成的部分应用,还有更多的功能需要全局变量。Cookie 的缺点主要集中于安全性和隐私保护。主要包括以下几种:
(1)Cookie 可能被禁用。当用户非常注重个人隐私保护时,他很可能禁用浏览器的 Cookie 功能; (2)Cookie 是与浏览器相关的。这意味着即使访问的是同一个页面,不同浏览器之间所保存的 Cookie 也是不能互相访问的; (3)Cookie 可能被删除。因为每个 Cookie 都是硬盘上的一个文件,因此很有可能被用户删除; (4)Cookie 安全性不够高。所有的 Cookie 都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。
Cookie 的设置与读取方法
设置 Cookie
每个 Cookie 都是一个名/值对,可以把下面这样一个字符串赋值给 document.cookie:
document.cookie="userId=828";
如果要一次存储多个名/值对,可以使用分号加空格(; )隔开,例如:
document.cookie="userId=828; userName=hulk";
在 Cookie 的名或值中不能使用分号(;)、逗号(,)、等号(=)以及空格。在 Cookie 的名中做到这点很容易,但要保存的值是不确定的。如何来存储这些值呢?方法是用 escape() 函数进行编码,它能将一些特殊符号使用十六进制表示,例如空格将会编码为“20%”,从而可以存储于 Cookie 值中,而且使用此种方案还可以避免中文乱码的出现。例如:
document.cookie="str="+escape("I love ajax");
相当于:
document.cookie="str=I%20love%20ajax";
当使用 escape() 编码后,在取出值以后需要使用 unescape() 进行解码才能得到原来的 Cookie 值,这在前面已经介绍过。
尽管 document.cookie 看上去就像一个属性,可以赋不同的值。但它和一般的属性不一样,改变它的赋值并不意味着丢失原来的值,例如连续执行下面两条语句:
document.cookie="userId=828";
document.cookie="userName=hulk";
这时浏览器将维护两个 Cookie,分别是 userId 和 userName,因此给 document.cookie 赋值更像执行类似这样的语句:
document.addCookie("userId=828");
document.addCookie("userName=hulk");
事实上,浏览器就是按照这样的方式来设置 Cookie 的,如果要改变一个 Cookie 的值,只需重新赋值,例如:
document.cookie="userId=929";
这样就将名为 userId 的 Cookie 值设置为了 929。
获取 Cookie 的值
下面介绍如何获取 Cookie 的值。Cookie 的值可以由 document.cookie 直接获得:
var strCookie=document.cookie;
这将获得以分号隔开的多个名/值对所组成的字符串,这些名/值对包括了该域名下的所有 Cookie。例如:
<script language="JavaScript" type="text/javascript">
<!--
document.cookie="userId=828";
document.cookie="userName=hulk";
var strCookie=document.cookie;
alert(strCookie);
//-->
</script>
从输出可知,只能够一次获取所有的 Cookie 值,而不能指定 Cookie 名称来获得指定的值,这正是处理 Cookie 值最麻烦的一部分。用户必须自己分析这个字符串,来获取指定的 Cookie 值,例如,要获取 userId 的值,可以这样实现:
<script language="JavaScript" type="text/javascript">
<!--
//设置两个cookie
document.cookie="userId=828";
document.cookie="userName=hulk";
//获取cookie字符串
var strCookie=document.cookie;
//将多cookie切割为多个名/值对
var arrCookie=strCookie.split("; ");
var userId;
//遍历cookie数组,处理每个cookie对
for(var i=0;i<arrCookie.length;i++){
var arr=arrCookie[i].split("=");
//找到名称为userId的cookie,并返回它的值
if("userId"==arr[0]){
userId=arr[1];
break;
}
}
alert(userId);
//-->
</script>
这样就得到了单个 Cookie 的值。
用类似的方法,可以获取一个或多个 Cookie 的值,其主要的技巧仍然是字符串和数组的相关操作。
Cookie 的过期、删除与路径域名控制
给 Cookie 设置终止日期
到现在为止,所有的 Cookie 都是单会话 Cookie,即浏览器关闭后这些 Cookie 将会丢失,事实上这些 Cookie 仅仅是存储在内存中,而没有建立相应的硬盘文件。
在实际开发中,Cookie 常常需要长期保存,例如保存用户登录的状态。这可以用下面的选项来实现:
document.cookie="userId=828; expiress=GMT_String";
其中 GMT_String 是以 GMT 格式表示的时间字符串,这条语句就是将 userId 这个 Cookie 设置为 GMT_String 表示的过期时间,超过这个时间,Cookie 将消失,不可访问。例如:如果要将 Cookie 设置为 10 天后过期,可以这样实现:
<script language="JavaScript" type="text/javascript">
<!--
//获取当前时间
var date=new Date();
var expiresDays=10;
//将date设置为10天以后的时间
date.setTime(date.getTime()+expiresDays*24*3600*1000);
//将userId和userName两个cookie设置为10天后过期
document.cookie="userId=828; userName=hulk; expires="+date.toGMTString();
//-->
</script>
删除 Cookie
为了删除一个 Cookie,可以将其过期时间设定为一个过去的时间,例如:
<script language="JavaScript" type="text/javascript">
<!--
//获取当前时间
var date=new Date();
//将date设置为过去的时间
date.setTime(date.getTime()-10000);
//将userId这个cookie删除
document.cookie="userId=828; expires="+date.toGMTString();
//-->
</script>
指定可访问 Cookie 的路径
默认情况下,如果在某个页面创建了一个 Cookie,那么该页面所在目录中的其他页面也可以访问该 Cookie。如果这个目录下还有子目录,则在子目录中也可以访问。例如在 www.xxxx.com/html/a.html 中所创建的 Cookie,可以被 www.xxxx.com/html/b.html 或 www.xxx.com/ html/ some/c.html 所访问,但不能被 www.xxxx.com/d.html 访问。
为了控制 Cookie 可以访问的目录,需要使用 path 参数设置 Cookie,语法如下:
document.cookie="name=value; path=cookieDir";
其中 cookieDir 表示可访问 Cookie 的目录。例如:
document.cookie="userId=320; path=/shop";
就表示当前 Cookie 仅能在 shop 目录下使用。
如果要使 Cookie 在整个网站下可用,可以将 cookie_dir 指定为根目录,例如:
document.cookie="userId=320; path=/";
指定可访问 Cookie 的主机名 和路径类似,主机名是指同一个域下的不同主机,例如:www.google.com 和 gmail.google.com 就是两个不同的主机名。默认情况下,一个主机中创建的 Cookie 在另一个主机下是不能被访问的,但可以通过 domain 参数来实现对其的控制,其语法格式为:
document.cookie="name=value; domain=cookieDomain";
以 google 为例,要实现跨主机访问,可以写为:
document.cookie="name=value;domain=.google.com";
这样,所有 google.com 下的主机都可以访问该 Cookie。
通用 Cookie 处理函数封装
综合示例:构造通用的 Cookie 处理函数
Cookie 的处理过程比较复杂,并具有一定的相似性。因此可以定义几个函数来完成 Cookie 的通用操作,从而实现代码的复用。下面列出了常用的 Cookie 操作及其函数实现。
1.添加一个 Cookie:addCookie(name,value,expiresHours)
该函数接收 3 个参数:Cookie 名称,Cookie 值,以及在多少小时后过期。这里约定 expiresHours 为 0 时不设定过期时间,即当浏览器关闭时 Cookie 自动消失。该函数实现如下:
<script language="JavaScript" type="text/javascript">
<!--
function addCookie(name,value,expiresHours){
var cookieString=name+"="+escape(value);
//判断是否设置过期时间
if(expiresHours>0){
var date=new Date();
date.setTime(date.getTime+expiresHours*3600*1000);
cookieString=cookieString+"; expires="+date.toGMTString();
}
document.cookie=cookieString;
}
//-->
</script>
2.获取指定名称的 Cookie 值:getCookie(name)
该函数返回名称为 name 的 Cookie 值,如果不存在则返回空,其实现如下:
<script language="JavaScript" type="text/javascript">
<!--
function getCookie(name){
var strCookie=document.cookie;
var arrCookie=strCookie.split("; ");
for(var i=0;i<arrCookie.length;i++){
var arr=arrCookie[i].split("=");
if(arr[0]==name)return arr[1];
}
return "";
}
//-->
</script>
3.删除指定名称的 Cookie:deleteCookie(name)
该函数可以删除指定名称的 Cookie,其实现如下:
<script language="JavaScript" type="text/javascript">
<!--
function deleteCookie(name){
var date=new Date();
date.setTime(date.getTime()-10000);
document.cookie=name+"=v; expires="+date.toGMTString();
}
//-->
</script>
以上所述就是本文的全部内容了,希望大家能够喜欢。