2025-04-17 日报 Day159

2025-04-17 日报 Day159

Yuyang 前端小白🥬

今日的鸡汤

和格局远大的人在一起,你的眼里就不会只有鸡毛蒜皮; 和自律向上的人在一起,你也会不由自主想要改变自己;和乐观豁达的人在一起,平凡的生活也能富有情趣。

今日学习内容

1、JS 红皮书 P751-758 第二十五章:客户端存储

今日笔记

1、客户端存储: 随着 Web 应用程序的出现,直接在客户端存储用户信息的需求也随之出现。这背后的想法是合理的:与特定用户相关的信息应该保存在用户的机器上。无论是登录信息、个人偏好,还是其他数据,Web 应用程序提供者都需要有办法把它们保存在客户端。对该问题的第一个解决方案就是 cookie,cookie 由古老的网景公司发明,由一份名为 Persistent Client State: HTTP Cookies 的规范定义。今天,cookie 只是在客户端存储数据的一个选项。
2、cookie: HTTP cookie 通常也叫作 cookie,最初用于在客户端存储会话信息。这个规范要求服务器在响应 HTTP 请求时,通过发送 Set-Cookie HTTP 头部包含会话信息。例如,下面是包含这个头部的一个 HTTP 响应:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value
这个 HTTP 响应会设置一个名为”name”,值为”value”的 cookie。名和值在发送时都会经过 URL 编码。浏览器会存储这些会话信息,并在之后的每个请求中都会通过 HTTP 头部 cookie 再将它们发回服务器,比如:
GET /index.jsl HTTP/1.1
Cookie: name=value
Other-header: other-header-value
这些发送回服务器的额外信息可用于唯一标识发送请求的客户端

  • 限制: cookie 是与特定域绑定的。设置 cookie 后,它会与请求一起发送到创建它的域。这个限制能保证 cookie 中存储的信息只对被认可的接收者开放,不被其他域访问。
    因为 cookie 存储在客户端机器上,所以为保证它不会被恶意利用,浏览器会施加限制。同时,cookie 也不会占用太多磁盘空间。
  • cookie 的构成: cookie 在浏览器中是由以下参数构成的。
     名称:唯一标识 cookie 的名称。cookie 名不区分大小写,因此 myCookie 和 MyCookie 是同一个名称。
     值:存储在 cookie 里的字符串值。
     域:cookie 有效的域。发送到这个域的所有请求都会包含对应的 cookie。这个值可能包含子域(如www.wrox.com),也可以不包含(如.wrox.com 表示对 wrox.com 的所有子域都有效)。如果不明确设置,则默认为设置 cookie 的域。
     路径:请求 URL 中包含这个路径才会把 cookie 发送到服务器。例如,可以指定 cookie 只能由http://www.wrox.com/books/访问,因此访问 http://www.wrox.com/下的页面就不会发送 cookie,即使请求的是同一个域。
     过期时间:表示何时删除 cookie 的时间戳(即什么时间之后就不发送到服务器了)。默认情况下,浏览器会话结束后会删除所有 cookie。不过,也可以设置删除 cookie 的时间。这个值是 GMT 格式(Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定删除 cookie 的具体时间。这样即使关闭浏览器 cookie 也会保留在用户机器上。把过期时间设置为过去的时间会立即删除 cookie。
     安全标志:设置之后,只在使用 SSL 安全连接的情况下才会把 cookie 发送到服务器。例如,请求 https://www.wrox.com 会发送 cookie,而请求 http://www.wrox.com 则不会。
    这些参数在 Set-Cookie 头部中使用分号加空格隔开,比如:
    HTTP/1.1 200 OK
    Content-type: text/html
    Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
    Other-header: other-header-value
    安全标志 secure 是 cookie 中唯一的非名/值对,只需一个 secure 就可以了。比如:
    HTTP/1.1 200 OK
    Content-type: text/html
    Set-Cookie: name=value; domain=.wrox.com; path=/; secure
    Other-header: other-header-value
    这里创建的 cookie 对所有 wrox.com 的子域及该域中的所有页面有效(通过 path=/指定)。不过,这个 cookie 只能在 SSL 连接上发送,因为设置了 secure 标志。
  • javascript 中的 cookie: 在 JavaScript 中处理 cookie 比较麻烦,因为接口过于简单,只有 BOM 的 document.cookie 属性。根据用法不同,该属性的表现迥异。要使用该属性获取值时,document.cookie 返回包含页面中所有有效 cookie 的字符串(根据域、路径、过期时间和安全设置),以分号分隔,如下面的例子所示:
    name1=value1;name2=value2;name3=value3
    所有名和值都是 URL 编码的,因此必须使用 decodeURIComponent()解码。在设置值时,可以通过 document.cookie 属性设置新的 cookie 字符串。这个字符串在被解析后会添加到原有 cookie 中。设置 document.cookie 不会覆盖之前存在的任何 cookie,除非设置了已有的 cookie。设置 cookie 的格式如下,与 Set-Cookie 头部的格式一样:
    name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
    在所有这些参数中,只有 cookie 的名称和值是必需的。下面是个简单的例子:
    document.cookie = “name=Nicholas”;
    这行代码会创建一个名为”name”的会话 cookie,其值为”Nicholas”。这个 cookie 在每次客户端向服务器发送请求时都会被带上,在浏览器关闭时就会被删除。虽然这样直接设置也可以,因为不需要在名称或值中编码任何字符,但最好还是使用 encodeURIComponent()对名称和值进行编码,比如:
    document.cookie = encodeURIComponent(“name”) + “=” + encodeURIComponent(“Nicholas”);
    要为创建的 cookie 指定额外的信息,只要像 Set-Cookie 头部一样直接在后面追加相同格式的字符串即可:
    document.cookie = encodeURIComponent(“name”) + “=” + encodeURIComponent(“Nicholas”) + “; domain=.wrox.com; path=/“;
    因为在 JavaScript 中读写 cookie 不是很直观,所以可以通过辅助函数来简化相应的操作。与 cookie 相关的基本操作有读、写和删除。这些在 CookieUtil 对象中表示如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class CookieUtil {
static get(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;
}
static set(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;
}
static unset(name, path, domain, secure) {
CookieUtil.set(name, "", new Date(0), path, domain, secure);
}
}
  • 子 cookie:
    为绕过浏览器对每个域 cookie 数的限制,有些开发者提出了子 cookie 的概念。子 cookie 是在单个
    cookie 存储的小块数据,本质上是使用 cookie 的值在单个 cookie 中存储多个名/值对。最常用的子 cookie
    模式如下:
    name1=value1&name2=value2&name3=value3&name4=value4&name5=value5
    子 cookie 的格式类似于查询字符串。这些值可以存储为单个 cookie,而不用单独存储为自己的名/值对。结果就是网站或 Web 应用程序能够在单域 cookie 数限制下存储更多的结构化数据。
    要操作子 cookie,就需要再添加一些辅助方法。解析和序列化子 cookie 的方式不一样,且因为对子 cookie 的使用而变得更复杂。比如,要取得某个子 cookie,就需要先取得 cookie,然后在解码值之前需要先像下面这样找到子 cookie:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class SubCookieUtil {
static get(name, subName) {
let subCookies = SubCookieUtil.getAll(name);
return subCookies ? subCookies[subName] : null;
}
static getAll(name) {
let cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null,
cookieEnd,
subCookies,
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 (let i = 0, len = subCookies.length; i < len; i++) {
parts = subCookies[i].split("=");
result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
}
return result;
}
}
return null;
}
// 省略其他代码
}
  • 使用cookie的注意事项: 还有一种叫作 HTTP-only 的 cookie。HTTP-only 可以在浏览器设置,也可以在服务器设置,但只能在服务器上读取,这是因为 JavaScript 无法取得这种 cookie 的值。
    因为所有 cookie 都会作为请求头部由浏览器发送给服务器,所以在 cookie 中保存大量信息可能会影响特定域浏览器请求的性能。保存的 cookie 越大,请求完成的时间就越长。即使浏览器对 cookie 大小有限制,最好还是尽可能只通过 cookie 保存必要信息,以避免性能问题。对 cookie 的限制及其特性决定了 cookie 并不是存储大量数据的理想方式。因此,其他客户端存储技术出现了。
此页目录
2025-04-17 日报 Day159