JavaScript高级程序设计第四版学习--第二十五章


title: JavaScript高级程序设计第四版学习–第二十五章
date: 2021-5-31 15:06:04
author: Xilong88
tags: JavaScript

本章内容
cookie
浏览器存储API
IndexedDB
可能出现的面试题:
1.了解过cookie吗?
2.了解过localStorage和sessionStorage吗?
3.了解过IndexDB吗?

HTTP cookie通常也叫作cookie ,最初用于在客户端存储会话信息。这个规范要求服务器在响应HTTP请求时,通过发送Set-Cookie HTTP头部包含会话信息。

这个HTTP响应会设置一个名为"name" ,值为"value" 的cookie。

知识点:

限制
cookie是与特定域绑定的。不被其他域访问

不超过300个cookie;
每个cookie不超过4096字节;
每个域不超过20个cookie;
每个域不超过81 920字节。

每个域能设置的cookie总数也是受限的,但不同浏览器的限制不同。例如:

最新版IE和Edge限制每个域不超过50个cookie;
最新版Firefox限制每个域不超过150个cookie;
最新版Opera限制每个域不超过180个cookie;
Safari和Chrome对每个域的cookie数没有硬性限制。

2.cookie的构成

名称 :唯一标识cookie的名称。cookie名不区分大小写,因
此myCookie 和MyCookie 是同一个名称。不过,实践中最好将
cookie名当成区分大小写来对待,因为一些服务器软件可能这样对
待它们。cookie名必须经过URL编码。
值 :存储在cookie里的字符串值。这个值必须经过URL编码。
域 :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

对www.wrox.com及其他wrox.com的子域

安全标志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

3.JavaScript中的cookie

在JavaScript中处理cookie比较麻烦,因为接口过于简单,只有BOM的document.cookie 属性。

所有名和值都是URL编码的,因此必须使用decodeURIComponent()解码。

4.子cookie

为绕过浏览器对每个域cookie数的限制,有些开发者提出了子cookie 的概念。子cookie是在单个cookie存储的小块数据,本质上是使用cookie的值在单个cookie中存储多个名/值对。最用的子cookie模式如下:

name=name1=value1&name2=value2&name3=value3&name4=value4&name5=value5

4.还有一种叫作HTTP-only 的cookie。HTTP-only可以在浏览器设置,也可以在服务器设置,但只能在服务器上读取,这是因为JavaScript无法取得这种cookie的值。

5.Web Storage

localStorage 和sessionStorage

Storage 的实例与其他对象一样,但增加了以下方法。

clear() :删除所有值;不在Firefox中实现。
getItem(name ) :取得给定 name 的值。
key(index ) :取得给定数值位置的名称。
removeItem(name ) :删除给定 name 的名/值对。
setItem(name , value ) :设置给定 name 的值。

sessionStorage 对象

sessionStorage 对象只存储会话数据,这意味着数据只会存储到浏览器关闭。这跟浏览器关闭时会消失的会话cookie类似。存储
在sessionStorage 中的数据不受页面刷新影响,可以在浏览器崩溃并重启后恢复。

sessionStorage 对象是Storage 的实例

localStorage 对象

在修订的HTML5规范里,localStorage 对象取代了globalStorage,作为在客户端持久存储数据的机制。要访问同一个localStorage 对象,页面必须来自同一个域(子域不可以)、在相同的端口上使用相同的协议。

localStorage 是Storage 的实例

// 使用方法存储数据
localStorage.setItem("name", "Nicholas");
// 使用属性存储数据
localStorage.book = "Professional JavaScript";
// 使用方法取得数据
let name = localStorage.getItem("name");
// 使用属性取得数据
let book = localStorage.book;

6.存储事件

使用属性或setItem() 设置值、使用delete 或removeItem() 删除值,以及每次调用clear() 时都会触发这个事件。这个事件的事件对象有如下4个属性。

domain :存储变化对应的域。
key :被设置或删除的键。
newValue :键被设置的新值,若键被删除则为null 。
oldValue :键变化之前的值。
window.addEventListener("storage",
    (event) => alert('Storage changed for ${event.domain}'));

7.IndexedDB

Indexed Database API简称IndexedDB ,是浏览器中存储结构化数据的一个方案。

使用IndexedDB数据库的第一步是调用indexedDB.open()方法,并给它传入一个要打开的数据库名称。如果给定名称的数据库已存在,则会发送一个打开它的请求;如果不存在,则会发送创建并打开这个数据库的请求。这个方法会返回IDBRequest 的实例,可以在这个实例上添加onerror 和onsuccess 事件处理程序。

let db,
    request,
    version = 1;
request = indexedDB.open("admin", version);
request.onerror = (event) =>
  alert(`Failed to open: ${
       event.target.errorCode}`);
request.onsuccess = (event) => {
     
  db = event.target.result;
};

对象存储

let user = {
     
  username: "007",
  firstName: "James",
  lastName: "Bond",
  password: "foo"
};
request.onupgradeneeded = (event) => {
     
  const db = event.target.result;

  // 如果存在则删除当前objectStore。测试的时候可以这样做
  // 但这样会在每次执行事件处理程序时删除已有数据
  if (db.objectStoreNames.contains("users")) {
     
    db.deleteObjectStore("users");
  }
  db.createObjectStore("users", {
      keyPath: "username" });
};

事务

创建了对象存储之后,剩下的所有操作都是通过事务 完成的。事务要通过调用数据库对象的transaction() 方法创建。任何时候,只要想要读取或修改数据,都要通过事务把所有修改操作组织起来。最简单的情况下,可以像下面这样创建事务:

let transaction = db.transaction();

如果不指定参数,则对数据库中所有的对象存储有只读权限。更具体的方式是指定一个或多个要访问的对象存储的名称:

let transaction = db.transaction("users");

这样可以确保在事务期间只加载users 对象存储的信息。如果想要访问多个对象存储,可以给第一个参数传入一个字符串数组:

let transaction = db.transaction(["users", "anotherStore"]);

要修改访问模式,可以传入第二个参数。这个参数应该是下列三个字符串之一:“readonly”、“readwrite"或"versionchange” 。比如:

let transaction = db.transaction("users", "readwrite");

有了事务的引用,就可以使用objectStore() 方法并传入对象存储的名称以访问特定的对象存储。然后,可以使用add() 和put() 方法添加和更新对象,使用get() 取得对象,使用delete() 删除对象,使用clear() 删除所有对象。

const transaction = db.transaction("users"),
    store = transaction.objectStore("users"),
    request = store.get("007");
request.onerror = (event) => alert("Did not get the object!");
request.onsuccess = (event) => alert(event.target.result.firstName);

因为一个事务可以完成任意多个请求,所以事务对象本身也有事件处理程序:onerror 和oncomplete 。这两个事件可以用来获取事务级的状态信息:

transaction.onerror = (event) => {
     
  // 整个事务被取消
};
transaction.oncomplete = (event) => {
     
  // 整个事务成功完成
};

add() 或put()

// users是一个用户数据的数组
let request,
    requests = [];
for (let user of users) {
     
  request = store.add(user);
  request.onerror = () => {
     
    // 处理错误
  };
  request.onsuccess = () => {
     
    // 处理成功
  };
  requests.push(request);
}

通过游标查询

使用事务可以通过一个已知键取得一条记录。如果想取得多条数据,则需要在事务中创建一个游标 。游标是一个指向结果集的指针。

需要在对象存储上调用openCursor() 方法创建游标。

const transaction = db.transaction("users"),

    store = transaction.objectStore("users"),
    request = store.openCursor();
request.onsuccess = (event) => {
     
  // 处理成功
};
request.onerror = (event) => {
     
  // 处理错误
};

这个IDBCursor 实例有几个属性。direction :字符串常量,表示游标的前进方向以及是否应该遍历所有重复的值。可能的值包括:

NEXT("next")NEXTUNIQUE("nextunique")PREV("prev")PREVUNIQUE("prevunique") 。
key :对象的键。
value :实际的对象。
primaryKey :游标使用的键。可能是对象键或索引键(稍后讨
论)。
request.onsuccess = (event) => {
     
  const cursor = event.target.result;
  if (cursor) {
      // 永远要检查
    console.log(`Key: ${
       cursor.key}, Value: ${
       JSON.stringify(cursor.value)}`);
  }
};

这个例子中的cursor.value 保存着实际的对象。正因为如此,在显示它之前才需要使用JSON来编码。

其他关于indexDB略,要用再看,感觉和后台关系更大。

你可能感兴趣的:(JavaScript学习,js,javascript,es6,前端)