JavaScript Cookie 进阶指南:玩转属性,精准控“盘”
在Web开发的世界里,Cookie是我们与用户“悄悄对话”的小帮手。它帮我们记住用户是谁、做过什么,从而实现登录状态保持、个性化设置等功能。但是,很多新手在初学Cookie时,往往只会简单地设置键值对,导致Cookie的生命周期混乱、作用范围失控。
今天,我们就来深入探讨JavaScript中那些让Cookie变得“智能”的核心属性:expires、max-age、path 和 domain。掌握它们,你就能精准地控制Cookie的每一个细节。
一、决定Cookie寿命:expires 与 max-age
默认情况下,我们创建的Cookie是会话级的。这意味着,一旦用户关闭浏览器,它就会被自动清除。想让Cookie“活”得更久,成为持久性Cookie,就需要用到 expires 或 max-age 属性。
1. expires 属性:指定“保质期”的终点
expires 属性是创建持久化Cookie最传统的方式。它接收一个具体的日期和时间字符串(UTC/GMT格式)。当系统时间超过这个设定值,浏览器就会无情地删除这个Cookie。
我个人在早期开发时很喜欢用它,因为它的语义非常直观:“请在这个具体的日期和时间之前,保留这个Cookie”。
代码示例:设置一个超长待机的Cookie
设想一个场景:我们正在开发一个名为“代码号学习编程”的网站,想要为用户(比如Duke Martin)设置一个长达数年的“记住我”功能,用expires属性再合适不过。
<!DOCTYPE html>
<html>
<head>
<title>代码号学习编程 - Cookie expires示例</title>
</head>
<body>
<h3>Cookie expires属性示例</h3>
<input type="button" value="【代码号】设置Cookie" onclick="setCookie()">
<input type="button" value="【代码号】获取Cookie" onclick="getCookie()">
<script>
function setCookie() {
// 设置一个有效期到2026年12月31日的Cookie
// 注意:这里的时间是UTC时间
document.cookie = "username=Duke Martin; expires=Thu, 31 Dec 2026 12:00:00 UTC";
alert('Cookie已设置,有效期至2026年底。');
}
function getCookie() {
if (document.cookie.length != 0) {
// 简单解析,实际项目中建议用更健壮的方法
var array = document.cookie.split("=");
alert("检测到Cookie: " + array[0] + " = " + array[1]);
} else {
alert("当前没有可用的Cookie,或Cookie已过期。");
}
}
</script>
</body>
</html>
2. max-age 属性:用“秒”计数的现在方式
与 expires 指定一个绝对时间点不同,max-age 属性采用相对时间,单位为秒。它告诉浏览器:“请在这个Cookie诞生后的XX秒内,一直保留它”。
在现在的项目中,我更倾向于使用 max-age。原因是它避免了客户端与服务器时间不同步引发的问题(如果用户电脑时间设错了,expires就失效了)。max-age 只看时间间隔,更加可靠。
代码示例:设置一个时效性的会话
假设在“代码号学习编程”里有一个限时优惠活动,我们希望用户的参与状态只持续24小时。
<!DOCTYPE html>
<html>
<head>
<title>代码号学习编程 - Cookie max-age示例</title>
</head>
<body>
<h3>Cookie max-age属性示例</h3>
<input type="button" value="【代码号】参与活动" onclick="setPromoCookie()">
<input type="button" value="【代码号】查看状态" onclick="getPromoCookie()">
<script>
function setPromoCookie() {
// 设置一个有效期为24小时的Cookie (60秒 * 60分钟 * 24小时)
var secondsInDay = 60 * 60 * 24;
document.cookie = "promo_status=entered; max-age=" + secondsInDay + ";";
alert('活动参与状态已记录,有效期24小时。');
}
function getPromoCookie() {
if (document.cookie.length != 0) {
// 更聪明的做法是遍历所有Cookie
var cookies = document.cookie.split('; ');
for (var i = 0; i < cookies.length; i++) {
var parts = cookies[i].split('=');
if (parts[0] === 'promo_status') {
alert("您的活动状态是:" + parts[1]);
return;
}
}
alert("未找到活动状态Cookie。");
} else {
alert("没有Cookie,活动已过期。");
}
}
</script>
</body>
</html>
【本节课程知识要点】
在现在Web开发中,除非有特殊需求(如兼容极古老的浏览器),否则优先考虑使用 max-age 属性来控制Cookie的生命周期,因为它基于时间间隔,不依赖于客户端时间的准确性。
二、扩展Cookie的作用域:path 与 domain
Cookie的“可见性”和“作用范围”由 path 和 domain 两个属性共同决定。如果设置不当,会出现“明明设置了Cookie,但在另一个页面死活拿不到”的尴尬情况。
1. path 属性:打破目录限制的钥匙
默认情况下,在 /user/profile.html 页面创建的Cookie,只能被 /user/ 目录及子目录(如 /user/settings.html)下的页面访问。它无法被根目录(/index.html)或他目录(如 /article/)下的页面读取。
path 属性就是用来打破这个限制的。通过设置 path=/,我们可以告诉浏览器:“请将这个Cookie的作用范围扩大到整个网站的根目录及所有子目录”。
我曾经在一个结构复杂的后台系统中被这个问题困扰了很久。当时在每个功能模块下都设置了不同的Cookie,导致系统各处状态不统一。后来,通过在设置核心登录态时统一加上 path=/,问题迎刃而解。
代码示例:让Cookie覆盖
假设你的网站目录结构如下,你想让在任何一个页面设置的Cookie,都能被共享。
你需要在所有页面的 setCookie 函数中都加上 path=/。
<!DOCTYPE html>
<html>
<head>
<title>代码号学习编程 - Cookie path示例</title>
</head>
<body>
<h3>Cookie path属性示例</h3>
<p>无论你在哪个页面设置,带上path=/,都能读取。</p>
<input type="button" value="【代码号】设置Cookie" onclick="setGlobalCookie()">
<input type="button" value="【代码号】读取Cookie" onclick="getGlobalCookie()">
<script>
function setGlobalCookie() {
// 关键点:path=/ 将这个Cookie的作用域设定为整个网站
document.cookie = "site_theme=dark; max-age=" + (60 * 60 * 24 * 30) + "; path=/;";
alert('主题Cookie已设置,有效期为一个月。');
}
function getGlobalCookie() {
if (document.cookie.length != 0) {
var cookies = document.cookie.split('; ');
for (var i = 0; i < cookies.length; i++) {
var parts = cookies[i].split('=');
if (parts[0] === 'site_theme') {
alert("当前主题是:" + parts[1]);
return;
}
}
alert("未找到主题Cookie。");
} else {
alert("没有可用的Cookie。");
}
}
</script>
</body>
</html>
2. domain 属性:打通子域之间的壁垒
domain 属性用于指定Cookie在哪个域名下有效。这个属性在处理单点登录或多子域共享状态时非常重要。
假设你的公司有多个子域:blog.ebingou.cn、shop.ebingou.cn 和 forum.ebingou.cn。你希望用户在 blog 登录后,访问 shop 时也能自动识别身份。这时,就需要设置 domain 属性。
经验分享:
-
如果设置
domain=ebingou.cn,则Cookie对ebingou.cn及所有子域(如blog.ebingou.cn、shop.ebingou.cn)都有效。这是最常用的做法。 -
如果设置
domain=blog.ebingou.cn,则该Cookie只对blog.ebingou.cn这个具体的子域有效,对他子域无效。
代码示例:跨子域共享用户信息
在 blog.ebingou.cn 上设置一个Cookie,希望 shop.ebingou.cn 也能读取到。
<!DOCTYPE html>
<html>
<head>
<title>代码号学习编程 - Cookie domain示例</title>
</head>
<body>
<h3>Cookie domain属性示例</h3>
<p>此页面运行在 blog.ebingou.cn 下</p>
<input type="button" value="【代码号】设置跨子域Cookie" onclick="setCrossDomainCookie()">
<script>
function setCrossDomainCookie() {
// 关键点:domain=.ebingou.cn (注意前面的点,代表所有子域)
// 为了共享登录态,也需要设置 path=/
document.cookie = "user_id=alan@ebingou.cn; domain=.ebingou.cn; path=/; max-age=" + (60 * 60 * 24);
alert('已在顶级域名 .ebingou.cn 下设置用户Cookie。你可以在 shop.ebingou.cn 下尝试读取。');
}
</script>
</body>
</html>
在 shop.ebingou.cn 的页面中,只需常规读取 document.cookie,就能看到 user_id 这个Cookie。
Cookie虽小,但五脏俱全。expires 和 max-age 决定了它的“寿命”,path 和 domain 则划定了它的“地盘”。理解并灵活运用这四个核心属性,是成为合格Web开发者的必修课。