元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
浏览器架构概览
多进程架构设计
浏览器内核组成
进程间通信机制
沙箱安全机制
浏览器加载页面流程
▶
渲染引擎原理
HTML解析算法
CSSOM构建过程
布局计算原理
图层合成机制
重绘与回流优化
▶
JavaScript引擎
V8执行流水线
事件循环机制
内存管理策略
JIT编译原理
垃圾回收算法
▶
网络栈实现
HTTP协议栈
缓存机制详解
资源加载策略
WebSocket实现
网络安全机制
▶
浏览器存储
Cookie管理机制
Web Storage实现
IndexedDB原理
缓存存储策略
▶
浏览器安全
同源策略实现
发布时间:
2025-03-23 15:47
↑
☰
# Web Storage实现原理 ## 概述 Web Storage是现代浏览器提供的客户端存储机制,包括localStorage和sessionStorage。本文将详细介绍Web Storage的实现原理、使用方法和最佳实践。 ## 基本概念 ### 1. 存储类型 #### localStorage - 持久化存储 - 不设过期时间 - 跨会话保持 - 同源访问 #### sessionStorage - 会话级存储 - 页面关闭即失效 - 不跨标签页共享 - 同源访问 ### 2. 存储限制 #### 容量限制 ```javascript // 检查存储容量 class StorageCapacity { constructor(type = 'localStorage') { this.storage = type === 'localStorage' ? localStorage : sessionStorage; } async checkAvailableSpace() { const testKey = '__storage_test__'; const testSize = 1024 * 1024; // 1MB let usedSpace = 0; try { // 计算已使用空间 for (let i = 0; i < this.storage.length; i++) { const key = this.storage.key(i); usedSpace += key.length + this.storage.getItem(key).length; } // 测试可用空间 const testData = 'a'.repeat(testSize); this.storage.setItem(testKey, testData); this.storage.removeItem(testKey); return { used: usedSpace, available: true, estimatedFree: testSize }; } catch (e) { return { used: usedSpace, available: false, error: e.message }; } } } ``` #### 限制处理 ```javascript // 存储限制处理 class StorageManager { constructor(type = 'localStorage') { this.storage = type === 'localStorage' ? localStorage : sessionStorage; this.capacity = new StorageCapacity(type); } async set(key, value) { try { const space = await this.capacity.checkAvailableSpace(); if (!space.available) { await this.cleanup(); } this.storage.setItem(key, JSON.stringify(value)); return true; } catch (e) { console.error('Storage set failed:', e); return false; } } async cleanup() { // 清理策略:删除最旧的项目 const items = this.getAllItems(); items.sort((a, b) => a.timestamp - b.timestamp); while (items.length > 0) { const item = items.shift(); this.storage.removeItem(item.key); const space = await this.capacity.checkAvailableSpace(); if (space.available) break; } } getAllItems() { const items = []; for (let i = 0; i < this.storage.length; i++) { const key = this.storage.key(i); const value = this.storage.getItem(key); try { const parsed = JSON.parse(value); items.push({ key, value: parsed, timestamp: parsed.timestamp || 0 }); } catch (e) { // 忽略无效的JSON数据 } } return items; } } ``` ## 实现机制 ### 1. 数据存储 #### 存储接口 ```javascript // 存储封装 class WebStorage { constructor(type = 'localStorage') { this.storage = type === 'localStorage' ? localStorage : sessionStorage; this.prefix = 'app_'; } setItem(key, value, options = {}) { const storageKey = this.prefix + key; const storageValue = { value, timestamp: Date.now(), ...options }; try { this.storage.setItem( storageKey, JSON.stringify(storageValue) ); return true; } catch (e) { console.error('Storage setItem failed:', e); return false; } } getItem(key) { const storageKey = this.prefix + key; try { const value = this.storage.getItem(storageKey); if (!value) return null; const parsed = JSON.parse(value); return parsed.value; } catch (e) { console.error('Storage getItem failed:', e); return null; } } removeItem(key) { const storageKey = this.prefix + key; try { this.storage.removeItem(storageKey); return true; } catch (e) { console.error('Storage removeItem failed:', e); return false; } } clear() { try { // 只清除带前缀的项 const keys = []; for (let i = 0; i < this.storage.length; i++) { const key = this.storage.key(i); if (key.startsWith(this.prefix)) { keys.push(key); } } keys.forEach(key => this.storage.removeItem(key)); return true; } catch (e) { console.error('Storage clear failed:', e); return false; } } } ``` #### 数据序列化 ```javascript // 数据序列化处理 class StorageSerializer { static serialize(value) { if (typeof value === 'undefined') { return 'undefined'; } if (value instanceof Date) { return ['__DATE__', value.toISOString()]; } if (value instanceof RegExp) { return ['__REGEXP__', value.toString()]; } if (typeof value === 'function') { return ['__FUNCTION__', value.toString()]; } if (Array.isArray(value)) { return value.map(item => this.serialize(item)); } if (typeof value === 'object' && value !== null) { const result = {}; for (const key in value) { if (value.hasOwnProperty(key)) { result[key] = this.serialize(value[key]); } } return result; } return value; } static deserialize(value) { if (value === 'undefined') { return undefined; } if (Array.isArray(value) && value.length === 2) { switch (value[0]) { case '__DATE__': return new Date(value[1]); case '__REGEXP__': const match = value[1].match(/\/(.*)\/([gimy]*)/); return new RegExp(match[1], match[2]); case '__FUNCTION__': return new Function('return ' + value[1])(); } } if (Array.isArray(value)) { return value.map(item => this.deserialize(item)); } if (typeof value === 'object' && value !== null) { const result = {}; for (const key in value) { if (value.hasOwnProperty(key)) { result[key] = this.deserialize(value[key]); } } return result; } return value; } } ``` ### 2. 事件机制 #### 存储事件 ```javascript // 存储事件监听 class StorageEventHandler { constructor() { this.handlers = new Map(); this.setupEventListener(); } setupEventListener() { window.addEventListener('storage', (event) => { // 只处理同源的存储事件 if (event.storageArea === localStorage) { this.handleStorageEvent(event); } }); } handleStorageEvent(event) { const handlers = this.handlers.get(event.key) || []; handlers.forEach(handler => { handler({ key: event.key, oldValue: JSON.parse(event.oldValue), newValue: JSON.parse(event.newValue), url: event.url }); }); } addHandler(key, handler) { if (!this.handlers.has(key)) { this.handlers.set(key, []); } this.handlers.get(key).push(handler); } removeHandler(key, handler) { if (!this.handlers.has(key)) return; const handlers = this.handlers.get(key); const index = handlers.indexOf(handler); if (index !== -1) { handlers.splice(index, 1); } } } ``` #### 变更通知 ```javascript // 存储变更通知 class StorageNotifier { constructor() { this.subscribers = new Set(); } subscribe(callback) { this.subscribers.add(callback); return () => this.unsubscribe(callback); } unsubscribe(callback) { this.subscribers.delete(callback); } notify(event) { this.subscribers.forEach(callback => { try { callback(event); } catch (e) { console.error('Storage notification error:', e); } }); } } ``` ## 性能优化 ### 1. 批量操作 #### 批处理器 ```javascript // 存储批处理 class StorageBatch { constructor(storage) { this.storage = storage; this.batch = new Map(); this.timer = null; } add(key, value) { this.batch.set(key, value); this.scheduleSave(); } scheduleSave() { if (this.timer) return; this.timer = setTimeout(() => { this.save(); this.timer = null; }, 100); } async save() { const operations = []; for (const [key, value] of this.batch) { operations.push( this.storage.setItem(key, value) ); } try { await Promise.all(operations); this.batch.clear(); } catch (e) { console.error('Batch save failed:', e); } } } ``` #### 缓存优化 ```javascript // 存储缓存 class StorageCache { constructor(storage) { this.storage = storage; this.cache = new Map(); this.maxSize = 100; } async get(key) { // 检查缓存 if (this.cache.has(key)) { return this.cache.get(key); } // 从存储获取 const value = await this.storage.getItem(key); if (value !== null) { this.cache.set(key, value); this.maintainCache(); } return value; } async set(key, value) { await this.storage.setItem(key, value); this.cache.set(key, value); this.maintainCache(); } maintainCache() { if (this.cache.size > this.maxSize) { const entries = Array.from(this.cache.entries()); entries.sort((a, b) => b[1].timestamp - a[1].timestamp); while (this.cache.size > this.maxSize) { const [key] = entries.pop(); this.cache.delete(key); } } } } ``` ### 2. 压缩存储 #### 数据压缩 ```javascript // 存储压缩 class StorageCompression { static async compress(data) { const jsonString = JSON.stringify(data); const blob = new Blob([jsonString]); try { const compressed = await new Response(blob.stream().pipeThrough( new CompressionStream('gzip') )).blob(); return await this.blobToBase64(compressed); } catch (e) { console.error('Compression failed:', e); return jsonString; } } static async decompress(data) { try { const blob = await this.base64ToBlob(data); const decompressed = await new Response(blob.stream().pipeThrough( new DecompressionStream('gzip') )).text(); return JSON.parse(decompressed); } catch (e) { console.error('Decompression failed:', e); return JSON.parse(data); } } static async blobToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); }); } static async base64ToBlob(base64) { const response = await fetch(base64); return response.blob(); } } ```