数据存储
Cookie
是直接存储在浏览器中的一小串数据
通常由 Web 服务器使用响应
Set-CookieHTTP-header 设置的,然后浏览器使用CookieHTTP-header 将它们自动添加到(几乎)每个对相同域的请求中
获取
- 值由 
name=value对组成,以;分隔。每一个都是独立的 cookie 
var cookie = document.cookie;
console.log(cookie)写入
- 只会更新其中对应 name 的 cookie,而不会涉及其他 cookie
 - cookie 的名称和值可以是任何字符。为了保持有效的格式,它们应该使用内建的 
encodeURIComponent函数对其进行转义encodeURIComponent编码后的name=value对,大小不能超过 4KB- 每个域的 cookie 总数不得超过 20+ 左右,具体限制取决于浏览器
 
 
document.cookie = 'user=yang' // 只会更新名称为 user 的 cookie
document.cookie = "user=yangwd; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
console.log(document.cookie)   // // 展示所有 cookie// 特殊字符(空格),需要编码
let name = "my name";
let value = "name value"
// 将 cookie 编码为 my%20name=name%20value
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);
console.log(document.cookie); // ...; my%20name=name%20value选项
path
path=/mypath,设置可访问该 cookie 的页面路径
- url 路径前缀必须是绝对路径,它使得该路径下的页面可以访问该 cookie,默认为当前路径
 - 如果一个 cookie 带有 
path=/admin设置,那么该 cookie 在/admin和/admin/something下都是可见的,但是在/home或/adminpage下不可见 - 通常将 
path设置为根目录:path=/,以使 cookie 对此网站的所有页面可见 
domain
domain=site.com,设置可访问 cookie 的域,但是在实际中,有一些限制。无法设置任何域
// 在 site.com
// 使 cookie 可以被在任何子域 *.site.com 访问:
document.cookie = "user=John; domain=site.com"expires | max-age
如果一个 cookie 没有设置这两个参数中的任何一个,那么在关闭浏览器之后,它就会消失,此类 cookie 被称为 "session cookie”
为了让 cookie 在浏览器关闭后仍然存在,需要设置
expires或max-age选项中的一个expires:过期时间,将其设置为过去的时间,则 cookie 会被删除max-age:过期时间距离当前时间的 秒 数,将其设置为 0 或负数,则 cookie 会被删除
日期必须完全采用 GMT 时区的这种格式。可以使用
date.toUTCString来获取它
expires=Tue, 19 Jan 2038 03:14:07 GMT
// 当前时间 +1 天
let date = new Date(Date.now() + 86400e3);
date = date.toUTCString();
document.cookie = "user=yang; expires=" + date;
// cookie 会在一小时后失效
document.cookie = "user=yang; max-age=3600";
// 删除 cookie(让它立即过期)
document.cookie = "user=yang; max-age=0";secure
设置 Cookie 应只能被通过 HTTPS 传输
- 默认情况下 cookie 是基于域的,它们不区分协议
 - 使用此选项,如果一个 cookie 是通过 
https://site.com设置的,那么它不会在相同域的 HTTP 环境下出现 
// 假设我们现在在 HTTPS 环境下
// 设置 cookie secure(只在 HTTPS 环境下可访问)
document.cookie = "user=yang; secure";httpOnly
Web 服务器使用
Set-Cookieheader 来设置 cookie,并且,它可以设置httpOnly选项这个选项禁止任何 JavaScript 访问 cookie。使用
document.cookie看不到此类 cookie,也无法对此类 cookie 进行操作
实用函数
当更新或删除一个 cookie 时,我们应该使用和设置 cookie 时相同的路径和域选项
获取 Cookie
/**
 * @param {Object} name 给定的 Cookie Name
 * 返回具有给定 name 的 cookie
 * 如果没找到,则返回 undefined
 * new RegExp 是动态生成的,以匹配 ; name=<value>
 * cookie 的值是经过编码的,所以 getCookie 使用了内建方法 decodeURIComponent 函数对其进行解码
 */
function getCookie(name) {
  let matches = document.cookie.match(new RegExp(
    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
  ));
  return matches ? decodeURIComponent(matches[1]) : undefined;
}设置 Cookie
/**
 * 将 cookie 的 name 设置为具有默认值 path=/(可以修改以添加其他默认值)和给定值 value
 */
function setCookie(name, value, options = {}) {
  options = {
    path: '/',
    // 如果需要,可以在这里添加其他默认值
    ...options
  };
  if (options.expires instanceof Date) {
    options.expires = options.expires.toUTCString();
  }
  let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);
  for (let optionKey in options) {
    updatedCookie += "; " + optionKey;
    let optionValue = options[optionKey];
    if (optionValue !== true) {
      updatedCookie += "=" + optionValue;
    }
  }
  document.cookie = updatedCookie;
}
// 使用范例:
setCookie('user', 'John', {
  secure: true,
  'max-age': 3600
});删除 Cookie
要删除一个 cookie,可以给它设置一个负的过期时间来调用它
function deleteCookie(name) {
  setCookie(name, "", {
    'max-age': -1
  })
}Storage
Web 存储对象
localStorage和sessionStorage允许在浏览器上保存键/值对在页面刷新后(对于
sessionStorage)甚至浏览器完全重启(对于localStorage)后,数据仍然保留在浏览器中
- 与 cookie 不同,Web 存储对象不会随每个请求被发送到服务器
 - 可以保存更多数据,大多数现代浏览器都允许保存至少 5MB 的数据(或更多),并且具有用于配置数据的设置
 - 服务器无法通过 HTTP header 操纵存储对象,一切都是在 JavaScript 中完成的
 - 存储绑定到源(域/协议/端口三者),不同协议或子域对应不同的存储对象,它们之间无法访问彼此数据
 - 键和值都必须是字符串,如果是任何其他类型,例数字或对象,它会被自动转换为字符串
 
区别
localStorage
- 在同源的所有标签页和窗口之间共享数据
 - 数据不会过期,它在浏览器重启甚至系统重启后仍然存在
 
sessionStorage
- 数据只存在于当前浏览器标签页 
- 具有相同页面的另一个标签页中将会有不同的存储
 - 在同一标签页下的 iframe 之间是共享的(假如它们来自相同的源)
 
 - 数据在页面刷新后仍然保留,但在关闭/重新打开浏览器标签页后不会被保留
 
方法、属性
两个存储对象都提供相同的方法和属性
setItem(key, value):存储键/值对getItem(key):按照键获取值removeItem(key):删除键及其对应的值clear():删除所有数据key(index):获取该索引下的键名length:存储的内容的长度
遍历
// 方式一
for(let i = 0; i < localStorage.length; i++) {
  let key = localStorage.key(i);
  console.log(`${key}: ${localStorage.getItem(key)}`);
}
// 方式二
for(let key in localStorage) {
  if (!localStorage.hasOwnProperty(key)) {
    continue; // 跳过像 "setItem","getItem" 等这样的键
  }
  console.log(`${key}: ${localStorage.getItem(key)}`);
}
// 方式三
let keys = Object.keys(localStorage);
for(let key of keys) {
  alert(`${key}: ${localStorage.getItem(key)}`);
}事件
当
localStorage或sessionStorage中的数据更新后,storage事件就会触发(在调用setItem,removeItem,clear方法后触发,将键作为对象属性来访问,不会触发storage事件)该事件会在所有可访问到存储对象的
window对象上触发,导致当前数据改变的window对象除外
event.key:发生更改的数据的key(如果调用的是.clear()方法,则为null)event.oldValue:旧值(如果是新增数据,则为null)event.newValue:新值(如果是删除数据,则为null)event.url:发生数据更新的文档的 urlevent.storageArea:发生数据更新的localStorage或sessionStorage对象