JavaScript怎么读写Cookie并设置过期时间

作者:竹影

时间:2026-10-30

浏览:275

详细讲解在 JavaScript 中如何使用 document.cookie 正确读取、写入 Cookie,并通过 Expires 与 Max-Age 设置过期时间与作用域,包含可复用的工具函数与常见注意事项。

文章目录

假设你在开发一个网页,需要保存用户选择的深色主题或提示弹窗的“今日不再显示”标记,并希望用户在关闭浏览器或数天后再打开时设置依然保留。此时使用 Cookie 进行本地状态标记是最直接的方案。在原生 JavaScript 中,所有对 Cookie 的操作均通过 document.cookie 接口完成,写入时赋值特定的键值指令串,并通过 max-age 或 expires 属性指定存活时长,读取时则需要对返回的聚合长字符串进行分割与反转义。

一、理解 document.cookie 的特殊访问机制

在 JavaScript 中操作 Cookie,最容易引起初学者困惑的是 document.cookie 的行为。它表面看起来是一个普通的字符串变量,但其实底层实现是一个特殊的访问器属性(getter/setter)。

当你向 document.cookie 赋值时,它并不会像普通变量那样直接覆盖现有的全部 Cookie。相反,它会解析你赋给它的这一小段指令,仅在浏览器存储池中新增或更新对应名称的单项 Cookie。而当你读取 document.cookie 时,浏览器会将当前页面域名和路径下所有未过期的键值对拼接在一起,以分号加空格(; )相连并返回一个长字符串,且所有存储属性(如有效路径、域名、过期时间等)都不会暴露在读取结果中。

JavaScript怎么读写Cookie并设置过期时间
图 1:document.cookie 的 Setter 增量修改机制与 Getter 聚合读取原理

二、写入 Cookie 并设置过期时间

如果不为写入的 Cookie 设置任何过期时间指令,浏览器默认会将其标记为“会话 Cookie”(Session Cookie)。这类 Cookie 仅保存在当前会话的内存中,一旦用户完全关闭浏览器,它就会被立即销毁。若要让 Cookie 持久化保存,必须显式指定过期时间。

1. 设置过期时间的两种标准语法

在 HTTP 及前端规范中,设置 Cookie 过期时间有两种方式:

  • max-age(推荐,相对时长):HTTP/1.1 引入的标准属性,单位为秒(Second)。例如 max-age=3600 表示当前写入后存活 1 小时;max-age=86400 表示存活 1 天。当设为 0 或负数时,浏览器会立即将该 Cookie 移除。
  • expires(传统标准,绝对时间):接受一个符合 GMT/UTC 格式的完整日期时间字符串(可由 Date.prototype.toUTCString() 生成)。例如 expires=Thu, 01 Jan 2026 00:00:00 GMT。
提示:在现代浏览器中,如果同一条 Cookie 赋值中同时包含了 max-age 和 expires,浏览器会严格以 max-age 为准。

2. 编写写入代码与关键参数

写入 Cookie 时,必须使用 encodeURIComponent 对键和值进行编码,避免等号、分号、空格或特殊字符破坏 Cookie 的基本格式语法。此外,强烈建议显式指定 path=/,确保整站根目录及各级子路径下均能正常共享访问该 Cookie,避免出现“在子页面写入却在首页无法读取”的路径隔离问题。

// 写入一个保存 7 天的 Cookie(使用现代标准的 max-age)
function setCookieWithMaxAge(name, value, days) {
  const seconds = days * 24 * 60 * 60;
  const encodedName = encodeURIComponent(name);
  const encodedValue = encodeURIComponent(value);
  
  // 拼接字符串并设置路径为根路径
  document.cookie = `${encodedName}=${encodedValue}; max-age=${seconds}; path=/; SameSite=Lax`;
}

// 写入一个保存 7 天的 Cookie(使用传统兼容的 expires)
function setCookieWithExpires(name, value, days) {
  const date = new Date();
  date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
  const expiresUTC = date.toUTCString();
  
  const encodedName = encodeURIComponent(name);
  const encodedValue = encodeURIComponent(value);
  
  document.cookie = `${encodedName}=${encodedValue}; expires=${expiresUTC}; path=/; SameSite=Lax`;
}
JavaScript怎么读写Cookie并设置过期时间
图 2:JavaScript 组装与写入 Cookie 的标准化操作流

三、读取与解析 Cookie

读取 Cookie 时,document.cookie 返回的是一个简单的非结构化字符串,格式形如:

"theme=dark; user=alice%20smith; isLogged=true; notification_closed=1"

每个 Cookie 项之间使用一个分号紧随一个空格(; )分隔开。浏览器并不提供 document.cookie.getItem(name) 这样的原生对象式读取接口,因此开发者必须通过算法将这个长字符串拆分并检索。

解析步骤

  1. 空值校验:首先检查 document.cookie 是否为空字符串。若未设置过 Cookie 或当前域名无可用项,则直接返回 null。
  2. 字符串切分:使用 split('; ') 将长字符串分割为单条 "key=value" 的子串数组。
  3. 精确查找:遍历数组,使用 startsWith(name + '=') 或 indexOf('=') 匹配指定的键名,避免部分匹配(例如查找 id 时误匹配到 user_id)。
  4. 解码还原:截取等号后面的值部分,并调用 decodeURIComponent 将其解码为原始文本。
JavaScript怎么读写Cookie并设置过期时间
图 3:Cookie 聚合字符串解析、检索与解码全流程

四、封装生产可用的 Cookie 操作工具集

在日常项目中,直接频繁拼接字符串既繁琐又极易引入编码或作用域错误。以下是一套兼顾健壮性与现代标准的完整工具函数,支持设置过期天数、作用域路径、安全标记以及单项删除。

/**
 * Cookie 操作工具集
 */
const CookieUtil = {
  /**
   * 设置 Cookie
   * @param {string} name Cookie 名称
   * @param {string} value Cookie 值
   * @param {number} [days=7] 有效天数,设为 0 则为会话 Cookie
   * @param {string} [path='/'] 作用域路径,默认为根目录
   * @param {boolean} [secure=false] 是否仅允许 HTTPS 传输
   */
  set(name, value, days = 7, path = '/', secure = false) {
    let cookieStr = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; path=${path}; SameSite=Lax`;
    
    if (typeof days === 'number' && days > 0) {
      // 换算为秒数,现代浏览器优先使用 max-age
      const maxAgeSeconds = Math.floor(days * 24 * 60 * 60);
      cookieStr += `; max-age=${maxAgeSeconds}`;
      
      // 同步提供 expires 以兼容极少数旧版浏览器引擎
      const expireDate = new Date();
      expireDate.setTime(expireDate.getTime() + days * 24 * 60 * 60 * 1000);
      cookieStr += `; expires=${expireDate.toUTCString()}`;
    }
    
    if (secure) {
      cookieStr += '; Secure';
    }
    
    document.cookie = cookieStr;
  },

  /**
   * 获取指定名称的 Cookie 值
   * @param {string} name Cookie 名称
   * @returns {string|null} 匹配到的值,未找到返回 null
   */
  get(name) {
    if (!document.cookie) return null;
    
    const prefix = `${encodeURIComponent(name)}=`;
    const parts = document.cookie.split('; ');
    
    for (let i = 0; i < parts.length; i++) {
      const item = parts[i];
      if (item.indexOf(prefix) === 0) {
        const rawValue = item.substring(prefix.length);
        try {
          return decodeURIComponent(rawValue);
        } catch (e) {
          return rawValue; // 容错回退
        }
      }
    }
    
    return null;
  },

  /**
   * 删除指定的 Cookie
   * @param {string} name Cookie 名称
   * @param {string} [path='/'] 创建时指定的路径
   */
  delete(name, path = '/') {
    // 核心原理:将 max-age 设为 0,并将 expires 设为过去的纪元时间
    document.cookie = `${encodeURIComponent(name)}=; path=${path}; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
  }
};

// 使用示例:
// 1. 设置一个存活 30 天的主题偏好
CookieUtil.set('theme', 'dark', 30);

// 2. 读取主题偏好
console.log(CookieUtil.get('theme')); // 输出: "dark"

// 3. 删除该配置
CookieUtil.delete('theme');
console.log(CookieUtil.get('theme')); // 输出: null

五、关键限制、安全策略与常见陷阱

在实际操作与维护 Cookie 时,还需要了解浏览器的底层限制与安全策略:

1. HttpOnly 属性的安全边界

由服务器在响应头(Set-Cookie: token=...; HttpOnly)中下发的 Cookie,拥有 HttpOnly 标记。这类 Cookie 受到浏览器的强保护,在客户端 JavaScript 的 document.cookie 中完全不可读、不可写、不可篡改。这是防范跨站脚本攻击(XSS)盗取用户身份凭证的黄金法则。因此,若发现某些认证 Cookie 无法在控制台打印或修改,并非代码逻辑出错,而是该 Cookie 属于 HttpOnly 属性。

2. 删除或覆盖时路径与域名不匹配

删除或更新一个已有 Cookie 时,指定的 path 和 domain 必须与当初创建该 Cookie 时的配置完全一致。如果最初在 /blog 路径下生成了一个 user=test,而在首页尝试用 path=/ 执行 max-age=0 进行删除,浏览器将视其为两个完全不同的 Cookie,导致旧的 Cookie 依然留在浏览器中。

3. 体积与数量配额限制

单个 Cookie 的总大小(包含键、值与所有属性字符串)通常不得超过 4KB(约 4096 字节)。同时,浏览器对单个域名下的 Cookie 数量通常限制在 20 到 50 个之间。若超出配额,旧的 Cookie 会被浏览器静默淘汰。因此,对于长文本、大量本地缓存数据或复杂对象,应优先使用 localStorage 或 IndexedDB,而非挤压 Cookie 空间。

JavaScript怎么读写Cookie并设置过期时间
图 4:Cookie 读写全生命周期规范与核心配置矩阵

六、总结

在 JavaScript 中管理 Cookie 的核心要点可以概括为:

  • 写入是增量修改:赋值给 document.cookie 仅改变指定键名项,不会抹去已有的其他 Cookie。
  • 过期时间控制:设置长期有效时,推荐使用 max-age=秒数,搭配 expires=UTC字符串 获得最佳兼容;删除 Cookie 时将 max-age 设为 0。
  • 路径必须显式:大部分业务场景中建议添加 path=/,确保全局互通,并在删除时使用相同路径。
  • 安全意识:涉及敏感登录状态的凭证应始终交由服务端设置 HttpOnly 与 Secure,普通轻量偏好设置才适合在前端由 JavaScript 自由读写。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章