简述cookie 、localStorage和sessionStorage

Web Storage规范

是HTML5的一部分

目的:克服由cookie带来的一些限制,当数据需要被严格的控制在客户端时,无须持续的将数据发回服务器。

目标

  • 提供一种cookie之外的存储会话数据的途径
  • 提供一种存储大量可以跨session存在的数据的机制

定义
Web Storage规范包含两种对象的定义:sessionStorage和globalStorage**。这两个对象在支持的浏览器中都是以 window 对象属性 的形式存在的。
注意:在使用之前记得查看其浏览器支持情况

Storage类型

Storage类型的方法:

  • clear(): 删除所有值
  • getItem(name): 根据指定的名字 name 获取对应的值
  • setItem(name, value): 为指定的name设置一个对应的值
  • key(index):获得index位置处的值的名字。
  • removeItem(name):删除name指定的键值对。
    还可以通过length属性来判断有多少键值对存放在Storage对象中

注意: Storage类型只能存储字符串。非字符串的数据在存储之前会被转换为字符串

sessionStorage对象

sessionStorage 对象是存储特定于某个会话的数据,当页面被重新加载时其仍然存在,只有当浏览器被关闭或者当前页面被关闭时,数据才会被清除;可以理解为数据被存储在浏览器中,只有浏览器被关闭后,数据才会被清除,同时,如果浏览器支持,在浏览器崩溃并重启之后仍然可以访问存储与sessionStorage中的数据

因为sessionStorage对象绑定于某个服务器会话,所以当文件在本地运行的时候是不可用的。

存储在sessionStorage中的数据只能由最初给对象存储数据的页面访问到,其只针对于当前会话,所以对多页面应用有限制

使用
sessionStorage对象是Storage的一个实例,所以可以使用setItem()或者直接设置新的属性存储数据
如:

// 使用方法存储数据
sessionStorage.setItem('name', 'Hexon');
// 使用属性存储数据
sessionStorage.book = 'Professional Javascript'; 

// 使用方法读取数据
var name = sessionStorage.getItem('name');
// 使用方法读取数据
var book = sessionStorage.book;

// 通过key来迭代存储与sessionStorage中的键值
for (var i = 0, len = sessionStorage.length; i < len; i++) {
  var key = sessionStorage.key(i);
  var value = sessionStorage.getItem(key);
  alert(key + '=' + value);
}

// 使用for-in循环迭代sessionStorage中的值
for (var key in sessionStorage) {
  val value = sessionstorage.getItem(key);
  alert(key + '=' + value);

不同的浏览器写入数据方面略有不同,FireFox和WebKit实现了同步写入,所以添加到存储空间中的数据是立刻被提交的。而IE的实现是异步写入数据,在设置数据和将数据写入磁盘之间可能有延迟

总结:sessionStorage对象应该只用于针对会话小段数据存储。如果需要跨会话存储数据,那么localStorage或者globalStorage更合适

globalStorage对象

只用FireFox2中实现了globalStorage对象,主要目的是为了实现 跨会话存储数据,但有特定的访问限制。

要使用globalStorage,首先要指定哪些域名可以访问该数据

使用方法

// 只针对 域名 wrox.com 的存储访问
globalStorage['wrox.com'].name = 'hexon';
var name = globaleStorage['wrox.com'].name;

注意:

  • globalStorage对象不是Storage的实例,而具体的globalStorage['wrox.com'] 才是
  • 当使用 globalStorage[''].name = 'hexon'来存储数据时,表示任何人都可以访问,一定不要这样做,不安全
  • 对globalStorage空间的访问,是依据发起请求的页面的域名、协议和端口 来限制的;如使用https协议在wrox.com中存储了数据,那么通过http访问的wrox.com的页面将无法访问该数据
  • 如果事先无法确定域名,那么使用 location.host 作为属性名比较安全,表示页面必须来自于同一个域名、协议和端口,才可以访问
  • 如果不使用removeItem() 或者 delete 删除,或者用户未清除浏览器缓存,存储在globalStorage属性中的数据将会一直保存在磁盘上

注意: globalStorage对象在修订过的HTML5规范中被localStorage对象所取代

localStorage 对象

localStorage对象在修订过的HTML5规范中作为持久保存客户端数据的方案取代了globalStorage

与globalStorage不同,不能给localStorage指定规则,规则在HTML5规范中就被制定,要访问同一个localStorage对象,页面必须来自同一个域名(子域名无效)、同一种协议,在同一端口上,这相当于 globalStorage[location.host]

localStorage是Storage类型的实例,因此可以像使用sessionStorage一样使用它

同时, 为了兼容只支持globalStorage对象的浏览器,可以使用以下方式进行能力检测:

function getLocalStorage() {
  if (tpyeof localStorage === 'object') {
     return localStorage;
  } else if (typeof globalStorage === 'object') {
     return globalStorage[location.host];
  }  else {
     throw new Error('Local Storage not available.');
  }
}

sessionStorage和localStorage的对比与使用

概念

这两者都是本地存储,均不会被发送到服务器端,其主要在生命周期上有比较明显的区别;localStorage的生命周期更长,没有过期时间,原则上要等到通过JavaScript将内容清除掉或者清空cookie时才会消失;而sessionStorage则在Browser或Tab被关闭时就会清空

限制

  • 对于localStorage而言,大多数桌面浏览器会设置每个来源5MB的限制,具体依浏览器而异
  • 对于sessionStorage,也因浏览器而异,一般每个来源在2.5MB ~ 5MB 之间

浏览器支持情况
这两者都都需要浏览器的API支持,浏览器的支持情况如下:

image.png

使用
通过window.localStoragewindow.sessionStorage这而两个对象进行操作

以操作localStorage为例:

  • 从存储中获取值
    window.localStorage.getItem('key')
function setStyles() {
  var currentColor = localStorage.getItem('bgcolor');
  var currentFont = localStorage.getItem('font');
  var currentImage = localStorage.getItem('image');

  document.getElementById('bgcolor').value = currentColor;
  document.getElementById('font').value = currentFont;
  document.getElementById('image').value = currentImage;

  htmlElem.style.backgroundColor = '#' + currentColor;
  pElem.style.fontFamily = currentFont;
  imgElem.setAttribute('src', currentImage);
}
  • 在存储中设置值
    window.localStorage.setItem可以从存储中获取指定的数据项或者设置新的数据项,该方法接受两个参数——要创建/修改的数据项的键,和对应的值。
function populateStorage() {
  localStorage.setItem('bgcolor', document.getElementById('bgcolor').value);
  localStorage.setItem('font', document.getElementById('font').value);
  localStorage.setItem('image', document.getElementById('image').value);
  setStyles();
}
  • 通过 StorageEvent 响应存储的变化
    无论何时,storage对象发生变化时(即创建/更新/删除,重复设置相同的项不会触发,storage.clear()方法至多触发一次),都会触发StorageEvent事件
    window.addEventListener('storage', function(){});
    示例:
window.addEventListener('storage', function(e) {  
  document.querySelector('.my-key').textContent = e.key;
  document.querySelector('.my-old').textContent = e.oldValue;
  document.querySelector('.my-new').textContent = e.newValue;
  document.querySelector('.my-url').textContent = e.url;
  document.querySelector('.my-storage').textContent = e.storageArea;
});

注意:在同一个页面内发生的改变不会起作用——在相同域名下的其他页面(如一个新标签或 iframe)发生的改变才会起作用。在其他域名下的页面不能访问相同的 Storage 对象。

  • 删除数据记录
    window.localStorage.removeItem():接收一个参数,要删除的数据项key值
    window.localStorage.clear():不接收参数,只是简单的清空域名对应的整个存储数据

cookie

起源: 最初由网景公司引入,用于在客户端存储回话信息

工作方式:要求服务器对任意HTTP请求,在响应头中添加Set-Cookie 字段来设置cookie,在客户端接收到这个cookie信息之后,将其存储起来,在此之后,当客户端再给创建它的域名发送HTTP请求时,都会在HTTP头中添加cookie信息,服务器可以根据这个cookie信息来决定该用户可以执行哪些操作(例如:是否允许它进行访问)

cookie的组成:
cookie由浏览器保存在客户端计算机中,由以下几块信息组成:

  • 名称:cookie的名称,这是唯一的,且字符不区分大小写。注意:cookie的名称必须是经过URL编码的
  • :存储在cookie中的字符串值。注意:值必须经过URL编码
  • :cookie对于哪个域有效,所有向该域发送的请求中,都会包含这个cookie信息,如果没有设置,则这个域会被认作是设置cookie的那个域
  • 路径:对于域下的路径访问,会包含cookie信息
  • 失效时间
  • 安全标志

一个服务器发给客户端的SetCookie信息,如下:

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; path=/; secure
Other-header: other-header-value

Set-cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT domain=.wrox.com; path=/; secure
这个Set-cookie的解释如下:

  • cookie名称: name
  • cookie的值:value (注意:值跟名称是不同的东西)
  • 失效时间:Mon, 22-Jan-07 07:10:24 GMT;(这是GMT时间)
  • 域名: .wrox.com
  • 路径: /
  • 安全标志: secure(只有当客户端通过SSH连接时,才可以传输该cookie)

cookie的特点

  • 创建方式:是由服务器来创建 cookie 信息的
  • 存放位置:客户端接收到服务器的cookie信息之后,将其存放在客户端的计算机中
  • cookie个数限制:cookie是绑定在域名下的,因此每个域的cookie个数是有限的,不同浏览器的限制不同,一般为50个,chrome和safari没有硬性限制。
  • cookie尺寸限制:对于每个域下的cookie的尺寸限制为4K字节注意:是一个域下的所有cookie的总尺寸之和要小于4K字节,不是单个cookie的尺寸
  • 失效时间:默认情况下,浏览器会话结束时即将所有的cookie删除,但是,可以自己设置失效时间,当未到达失效时间时,cookie将一直保存在客户端计算机中,除非自己手动删除
  • cookie会被附加在每个http请求中,因此会增加流量
  • 安全标志:当指定后(通过Set-Cookie中添加 secure 关键字即可),cookie只有在使用SSL连接的时候才发送到服务器

注意事项

  • cookie个数和尺寸的限制,超过限制后,不同的浏览器有不同的处理方式,因此,一定不要超过限制
  • 域、路径、失效时间和secure标志都是服务器给浏览器的指示,以指定何时应该发送cookie,这些参数不会作为发送给服务器cookie信息的一部分
  • cookie的名称是经过URL编码的,注意:是名称
  • Javascipt中处理cookie有些复杂,主要是接口不好用,即:document.cookie

cookie的缺陷

  • cookie会被附加在每个http请求中,因此会无形中增加流量
  • 由于http请求中的cookie是明文传输,因此有安全问题(除非使用https),不要使用cookie存放重要的数据
  • cookie的大小限制是4kb,对于复杂的存储需求可能不够用

cookie的使用

  • 获取cookie:document.cookie,通过该方法可以获取cookie
  • 删除cookie:设置document.cookie并不会覆盖cookie,除非设置的cookie的名称已经存在。那么就会对原cookie进行覆盖
    封装的cookie代码
let CookieUtil = {
    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;
    },
    set: function (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;
    },

    // 删除cookie, 并没有直接的删除cookie的方法,这里通过重新设置cookie名称,来对cookie进行替换
    // 同时 将过期时间expires设置为过去的时间,
    unset: function(name, path, domain, secure) {
      this.set(name, '', new Date(0), path, domain, secure);
    }
  }

浏览器本地存储中 cookie 和 localStorage 有什么区别? localStorage 如何存储删除数据。

sessionStorage、localStorage和cookie 这三者都是用于浏览器端存储数据,而且都是字符串类型的键值对

区别在于:

  • 数据传输方面:在每个http请求中都会附加cookie信息,cookie中的信息能够被推送到服务器端;而sessionStorage和localStorage不会被推送到服务器端
  • 存储大小不同:cookie最大支持4KB,而sessionStorage和localStorage一般在2.5~10MB
  • 生命周期:默认情况下,cookie开始于浏览器启动,结束于浏览器关闭,但是可以手动设置cookie的过期时间,同时,到期后被删除;而对于localStorage,没有过期时间,原则上只要不手动删除,其会一直被保存在本地上,sessionStorage的数据关闭浏览器时清除
  • 被创造的初衷不同:sessionStorage和localStorage都属于WebStorage,创建他们的目的就是用于存储客户端数据;
    而cookie最早在网景的浏览器中被支持,主要目的是为了辨别用户身份而存储在本地终端的数据。

参考:在HTML5的时代,重新认识Cookie


参考:


推荐阅读更多精彩内容