面试官:除了Cookie和Web Storage,你还知道其他浏览器的存储方式吗?知道IndexedDB吗?
前记
浏览器存储方式一直是面试中提问的关注点(我碰上的面试),是Web浏览器用来再本地存储数据的不同方法和技术,这些存储方式用于Web应用程序中保存和检索数据,以改善用户体验 、提高性能 和实现离线功能。
Cookie
概念
Cookie (cookie前端开发中通常称为"HTTP Cookie")是一种用于Web浏览器和Web服务器之间存储小型数据 的机制,经常用于跟踪用户、维护用户会话状态以及存储有关用户首选项和其他信息的数据
工作原理
- 当访问一个网站时,服务器可能会在响应中包含一个或多个Cookie.
- 浏览器会将这些Cookie保存在用户计算机上的Cookie文件中,通常是一个文本文件.
- 当访问该网站和其他网页时,浏览器会将相关的Cookie信息包含在HTTP请求头中发送给服务器.
- 服务器根据这些Cookie来识别用户、维护会话状态和提供个性化内容.
使用场景
- 会话管理:Cookie通常用于跟踪用户会话,使用户在登录后保持登录状态,直到退出登录或关闭浏览器.
- 个性化体验:网站可以使用Cookie存储用户首选择、语言偏好、主题等信息,以提供个性化的用户体验.
- 购物车:在电子商务网站上,Cookie常用于存储购物车中的商品信息,以便用户在不同的页面之间保持购物车状态.
- 广告跟踪:广告商可以使用Cookie来跟踪用户的浏览器行为,以投放相关广告.
- 分析和统计:Cookie可以用于手机用户访问网站的信息,以进行分析和统计.
安全性考虑
- Cookie中的数据可以被篡改,因此不应存储敏感信息,eg:密码.
- 针对Cookie的安全措施包括使用HTTPS传输和设置HttpOnly标志,以防止xss攻击.
使用方式
- 设置Cookie
js
document.cookie = "username=John Doe; expires=Thu, 31 Dec 2023 23:59:59 UTC; path=/";
使用document.cookie属性来设置Cookie,Cookie是一个字符串,其中包含一个或多个键值对,以分号和空格分隔。
- 读取Cookie
js
const allCookies = document.cookie;
// 解析Cookie字符串以获取特定的值
const cookiesArray = allCookies.split("; ");
for (const cookie of cookiesArray) {
const [name, value] = cookie.split("=");
if (name === "username") {
console.log(`Username is: ${value}`);
break;
}
}
- 删除Cookie
js
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
要删除Cookie,可以使用通过设置Cookie的过期时间为一个过去的日期来使其失效。
LocalStorage (Web Storage)
概念
LocalStorage 是一种 Web 浏览器提供的客户端存储机制,允许开发人员在用户的浏览器中永久性地存储键值对数据。这些数据在用户的浏览器关闭后仍然保持不变,直到被显式删除。
工作原理
- LocalStorage 使用键值对的方式存储数据,每个数据项都有一个唯一的键名和一个与之相关联的值.
- 数据存储在用户的浏览器中,通常存储在一个特定的存储区域内,以供特定网站或域名访问.
- 与Cookie不同,LocalStorage 的数据不会在每个HTTP请求中发送到服务器,这使得其更适合存储大量数据。通常的容量限制在5-10MB,在不同浏览器可能会略微不同的容量限制,如果存储超出容量限制,浏览器通常会提示用户清理存储或提供警告.
作用域
LocalStorage 的数据在同一域名下的所有页面中共享,包括子域名。这意味着,如果在 example.com
上设置了LocalStorage数据,那么将在www.example.com
和 blog.example.com
等子域下也是可见的。
生命周期
LocalStorage 的数据是持久性的,它们不会因为用户关闭浏览器或计算机而丢失,除非通过JavaScript代码显式删除或覆盖。
安全性考虑
- LocalStorage 中的数据存储在用户的浏览器中,因此不应存储敏感信息,eg:密码、信用卡号.
- 持续对LocalStorage中的数据进行检验和验证,以防止潜在的安全问题.
使用场景
- LocalStorage 适用于需要在用户浏览器中永久性存储数据的情况,eg:用户首选项、本地缓存、离线数据.
- 通常用于提高性能,因为它允许在 Web 应用程序在多次访问之间保留数据,而无需每次都从服务器请求.
使用方式
- 设置数据
js
localStorage.setItem('username', 'Tsheep');
- 获取数据
js
const username = localStorage.getItem('username');
- 删除数据
js
localStorage.removeItem('username');
- 清空所有数据
js
localStorage.clear();
SessionStorage(Web Storage)
概念
SessionStorage是一种 Web 浏览器提供的客户端存储机制,与 LocalStorage 类似,但具有一些重要的区别,它允许开发人员在用户的浏览器中存储键值对数据,但这些数据仅在当前浏览器会话期间有效,一旦用户关闭浏览器标签或窗口,SessionStorage中的数据即被删除。
工作原理
- SessionStorage使用键值对方式存储数据,每个数据项都有一个唯一的键名和一个与之相关联的值.
- 数据存储在用户的浏览器中,但与LocalStorage不同,SessionStorage的数据仅在当前浏览器会话期间有效.
- 当用户关闭浏览器标签或窗口时,SessionStorage 中的数据将被删除,这意味着数据的生命周期受限于当前会话.
- SessionStorage 容量通常与 LocalStorage 相同,约为5-10MB,但不同浏览器可能有略微不同的容量限制.
作用域
- SessionStorage 的数据仅在统一浏览器窗口或标签页中共享,如果用户在不同的窗口和标签页中打开相同的网站,每个窗口/标签页都有自己独立的SessionStorage.
- 这使得 SessionStorage 非常适合在单个浏览器会话中共享数据,但不适合在不同浏览器窗口之间共享数据.
安全性考虑
由于SessionStorage 的数据生命周期短暂,通常不同于存储敏感信息。然而,如任何客户端存储机制一样,数据仍然可以被访问和篡改,因此不应存储敏感信息。
使用场景
- SessionStorage 适用于需要在单个浏览器会话期间存储数据,eg:购物车数据、表单数据、临时状态等.
- 对于在不同浏览器窗口或标签之间共享数据不适用,因为每个窗口/标签页都有自己独立的 SessionStorage.
使用方法
- 设置数据
js
sessionStorage.setItem('username', 'Tsheep');
- 获取数据
js
const username = sessionStorage.getItem('username');
- 删除数据
js
sessionStorage.removeItem('username');
- 清空所有数据
js
sessionStorage.clear();
IndexedDB
概念
IndexedDB (Indexed Database)是一种高级的客户端存储技术,用于在浏览器中存储结构化数据,与传统的 Web 存储机制(上面的三个)不同,IndexedDB允许以键值对的方式存储和检索大量数据,并支持复杂的查询操作。
工作原理
- IndexedDB 使用一个数据库来存储数据,该数据库包含多个对象存储,每个对象存储都可以存储不同类型的数据.
- 每个对象存储包含一个键值对集合,其中每个数据都有一个唯一的键,以便进行检索和索引.
- IndexedDB 使用异步API,这意味着所有与数据库的交互都是非堵塞的,不会阻止主线程的执行.
容量限制
IndexedDB 通常具有较高的容量限制,通常在几十MB到数百MB之间,具体限制取决于浏览器和操作系统。
事务管理
- IndexedDB 使用事务(Transaction)来管理数据库操作,包括读取、写入、更新和删除数据.
- 事务是原子性的,要么全部成功,要么全部失败。这有助于确保数据的一致性和完整性.
索引
- IndexedDB 允许创建索引以加速数据检索操作,索引可以基于特定数据字段,允许高效地查询和排序数据.
- 索引是可选地,可以选择为需要加速的字段创建索引.
查询
- IndexedDB 支持强大的查询功能,允许按范围、键、索引等多种条件进行查询.
- 可以使用游标(Cursor)来遍历查询结果集.
异步API
- IndexedDB API 是异步的,通常使用Promise或回调函数来处理操作的成功和失败.
- 这确保了数据库操作不会阻塞主线程,从而提高了 Web 应用程序的性能和响应能力.
安全性
- 与其他客户端存储方式不同,IndexedDB 通常不受同源策略的限制,这使得它更适合跨域请求和存储数据.
- 浏览器仍然对IndexedDB的访问进行控制,以确保数据的安全性.
使用场景
- IndexedDB 适用于需要存储大量数据的 Web 应用程序,如离线应用程序、数据仓库、复杂的数据操作等.
- 特别适用于需要离线访问数据的情况,因为数据存储在客户端,不依赖于网络连接.
使用方法
js
// 打开或创建数据库
const dbPromise = indexedDB.open('myDatabase', 1);
// 处理数据库版本更新
dbPromise.onupgradeneeded = function (event) {
const db = event.target.result;
// 创建一个名为"myObjectStore"的对象存储
const objectStore = db.createObjectStore('myObjectStore', { keyPath: 'id' });
// 创建一个名为"nameIndex"的索引,用于根据"name"字段检索数据
objectStore.createIndex('nameIndex', 'name', { unique: false });
};
// 处理数据库打开成功
dbPromise.onsuccess = function (event) {
const db = event.target.result;
// 开始一个事务
const transaction = db.transaction('myObjectStore', 'readwrite');
// 获取对象存储
const objectStore = transaction.objectStore('myObjectStore');
// 添加数据到对象存储
const data = { id: 1, name: 'Tsheep', email: 'Tsheep@example.com' };
objectStore.add(data);
// 提交事务
transaction.oncomplete = function () {
console.log('数据已添加到对象存储');
};
transaction.onerror = function () {
console.error('添加数据时出错');
};
};
// 处理数据库打开失败
dbPromise.onerror = function (event) {
console.error('无法打开数据库');
};
// 检索数据
dbPromise.then(function (db) {
const transaction = db.transaction('myObjectStore', 'readonly');
const objectStore = transaction.objectStore('myObjectStore');
// 使用索引进行查询
const index = objectStore.index('nameIndex');
const request = index.get('Tsheep');
request.onsuccess = function () {
const result = request.result;
if (result) {
console.log('检索到数据:', result);
} else {
console.log('未找到匹配的数据');
}
};
request.onerror = function () {
console.error('检索数据时出错');
};
});
这里创建了一个名为myDatabase
的indexedDB的数据库,其中包含一个名为myObjectStore
的对象存储和一个名为nameIndex
的索引,然后打开数据库,创建事务并在对象存储中添加数据,最后,使用索引来检索数据。