Skip to content

存储机制

存储方式对比

浏览器提供多种存储方式,各有优缺点和适用场景。

存储方式容量过期时间作用域用途
Cookie4KB可设置同源会话管理、个性化
LocalStorage5-10MB永久同源长期存储
SessionStorage5-10MB会话结束同源标签页临时存储
IndexedDB大容量永久同源结构化数据
WebSQL大容量永久同源结构化数据(已废弃)

基本用法

javascript
// 设置Cookie
document.cookie = 'name=value';

// 设置过期时间
document.cookie = 'name=value; expires=Wed, 21 Oct 2024 07:28:00 GMT';

// 设置路径
document.cookie = 'name=value; path=/';

// 设置域名
document.cookie = 'name=value; domain=example.com';

// 设置安全标志
document.cookie = 'name=value; secure';

// 设置HttpOnly标志
document.cookie = 'name=value; HttpOnly';

// 设置SameSite
document.cookie = 'name=value; SameSite=Strict';

读取Cookie

javascript
// 读取所有Cookie
console.log(document.cookie);

// 解析Cookie
function getCookie(name) {
  const cookies = document.cookie.split(';');
  for (let cookie of cookies) {
    const [key, value] = cookie.trim().split('=');
    if (key === name) {
      return value;
    }
  }
  return null;
}

const value = getCookie('name');
console.log(value);

删除Cookie

javascript
// 删除Cookie
document.cookie = 'name=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';

Cookie属性

javascript
// 完整示例
document.cookie = 'name=value; expires=Wed, 21 Oct 2024 07:28:00 GMT; path=/; domain=example.com; secure; HttpOnly; SameSite=Strict';

LocalStorage

基本用法

javascript
// 设置数据
localStorage.setItem('key', 'value');

// 读取数据
const value = localStorage.getItem('key');
console.log(value);

// 删除数据
localStorage.removeItem('key');

// 清空所有数据
localStorage.clear();

// 获取所有键
for (let i = 0; i < localStorage.length; i++) {
  const key = localStorage.key(i);
  const value = localStorage.getItem(key);
  console.log(key, value);
}

存储对象

javascript
// 存储对象
const user = {
  name: 'John',
  age: 30,
  email: 'john@example.com'
};

localStorage.setItem('user', JSON.stringify(user));

// 读取对象
const userJson = localStorage.getItem('user');
const userObj = JSON.parse(userJson);
console.log(userObj);

监听变化

javascript
// 监听LocalStorage变化
window.addEventListener('storage', (event) => {
  console.log('Key:', event.key);
  console.log('Old Value:', event.oldValue);
  console.log('New Value:', event.newValue);
  console.log('URL:', event.url);
});

SessionStorage

基本用法

javascript
// 设置数据
sessionStorage.setItem('key', 'value');

// 读取数据
const value = sessionStorage.getItem('key');
console.log(value);

// 删除数据
sessionStorage.removeItem('key');

// 清空所有数据
sessionStorage.clear();

与LocalStorage的区别

javascript
// LocalStorage: 永久存储,同源所有标签页共享
localStorage.setItem('key', 'value');

// SessionStorage: 会话结束清除,只对当前标签页有效
sessionStorage.setItem('key', 'value');

IndexedDB

基本用法

javascript
// 打开数据库
const request = indexedDB.open('myDatabase', 1);

request.onerror = function(event) {
  console.error('Database error:', event.target.error);
};

request.onsuccess = function(event) {
  const db = event.target.result;
  console.log('Database opened successfully');
};

request.onupgradeneeded = function(event) {
  const db = event.target.result;
  
  // 创建对象存储
  const objectStore = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
  
  // 创建索引
  objectStore.createIndex('name', 'name', { unique: false });
  objectStore.createIndex('email', 'email', { unique: true });
};

添加数据

javascript
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = function(event) {
  const db = event.target.result;
  
  const transaction = db.transaction(['users'], 'readwrite');
  const objectStore = transaction.objectStore('users');
  
  const user = {
    name: 'John',
    age: 30,
    email: 'john@example.com'
  };
  
  const addRequest = objectStore.add(user);
  
  addRequest.onsuccess = function(event) {
    console.log('Data added successfully');
  };
  
  addRequest.onerror = function(event) {
    console.error('Add error:', event.target.error);
  };
};

读取数据

javascript
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = function(event) {
  const db = event.target.result;
  
  const transaction = db.transaction(['users'], 'readonly');
  const objectStore = transaction.objectStore('users');
  
  const getRequest = objectStore.get(1);
  
  getRequest.onsuccess = function(event) {
    const user = event.target.result;
    console.log(user);
  };
};

更新数据

javascript
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = function(event) {
  const db = event.target.result;
  
  const transaction = db.transaction(['users'], 'readwrite');
  const objectStore = transaction.objectStore('users');
  
  const user = {
    id: 1,
    name: 'John',
    age: 31,
    email: 'john@example.com'
  };
  
  const putRequest = objectStore.put(user);
  
  putRequest.onsuccess = function(event) {
    console.log('Data updated successfully');
  };
};

删除数据

javascript
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = function(event) {
  const db = event.target.result;
  
  const transaction = db.transaction(['users'], 'readwrite');
  const objectStore = transaction.objectStore('users');
  
  const deleteRequest = objectStore.delete(1);
  
  deleteRequest.onsuccess = function(event) {
    console.log('Data deleted successfully');
  };
};

查询数据

javascript
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = function(event) {
  const db = event.target.result;
  
  const transaction = db.transaction(['users'], 'readonly');
  const objectStore = transaction.objectStore('users');
  const index = objectStore.index('name');
  
  const getRequest = index.get('John');
  
  getRequest.onsuccess = function(event) {
    const user = event.target.result;
    console.log(user);
  };
};

存储封装

LocalStorage封装

javascript
class Storage {
  constructor(prefix = 'app_') {
    this.prefix = prefix;
  }
  
  set(key, value) {
    const data = JSON.stringify(value);
    localStorage.setItem(this.prefix + key, data);
  }
  
  get(key) {
    const data = localStorage.getItem(this.prefix + key);
    return data ? JSON.parse(data) : null;
  }
  
  remove(key) {
    localStorage.removeItem(this.prefix + key);
  }
  
  clear() {
    const keys = Object.keys(localStorage);
    keys.forEach(key => {
      if (key.startsWith(this.prefix)) {
        localStorage.removeItem(key);
      }
    });
  }
}

const storage = new Storage();
storage.set('user', { name: 'John', age: 30 });
const user = storage.get('user');
console.log(user);

IndexedDB封装

javascript
class IndexedDBHelper {
  constructor(dbName, version) {
    this.dbName = dbName;
    this.version = version;
    this.db = null;
  }
  
  async open() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version);
      
      request.onsuccess = () => {
        this.db = request.result;
        resolve(this.db);
      };
      
      request.onerror = () => {
        reject(request.error);
      };
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        this.onUpgrade(db, event.oldVersion, event.newVersion);
      };
    });
  }
  
  onUpgrade(db, oldVersion, newVersion) {
    // 子类实现
  }
  
  async add(storeName, data) {
    const transaction = this.db.transaction([storeName], 'readwrite');
    const objectStore = transaction.objectStore(storeName);
    
    return new Promise((resolve, reject) => {
      const request = objectStore.add(data);
      
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
  
  async get(storeName, key) {
    const transaction = this.db.transaction([storeName], 'readonly');
    const objectStore = transaction.objectStore(storeName);
    
    return new Promise((resolve, reject) => {
      const request = objectStore.get(key);
      
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
  
  async update(storeName, data) {
    const transaction = this.db.transaction([storeName], 'readwrite');
    const objectStore = transaction.objectStore(storeName);
    
    return new Promise((resolve, reject) => {
      const request = objectStore.put(data);
      
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
  
  async delete(storeName, key) {
    const transaction = this.db.transaction([storeName], 'readwrite');
    const objectStore = transaction.objectStore(storeName);
    
    return new Promise((resolve, reject) => {
      const request = objectStore.delete(key);
      
      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }
}

class UserDB extends IndexedDBHelper {
  constructor() {
    super('UserDB', 1);
  }
  
  onUpgrade(db, oldVersion, newVersion) {
    if (oldVersion < 1) {
      const objectStore = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
      objectStore.createIndex('name', 'name', { unique: false });
      objectStore.createIndex('email', 'email', { unique: true });
    }
  }
}

const userDB = new UserDB();
userDB.open().then(() => {
  return userDB.add('users', { name: 'John', age: 30, email: 'john@example.com' });
}).then((id) => {
  console.log('User added with ID:', id);
});

面试常见问题

1. Cookie、LocalStorage和SessionStorage的区别?

  • Cookie: 容量小(4KB),可设置过期时间,每次请求都会发送
  • LocalStorage: 容量大(5-10MB),永久存储,不发送到服务器
  • SessionStorage: 容量大(5-10MB),会话结束清除,不发送到服务器

2. IndexedDB的特点?

  • 大容量存储
  • 异步API
  • 支持事务
  • 支持索引
  • 支持复杂查询

3. 如何监听LocalStorage变化?

javascript
window.addEventListener('storage', (event) => {
  console.log('Key:', event.key);
  console.log('Old Value:', event.oldValue);
  console.log('New Value:', event.newValue);
});

4. Cookie的属性有哪些?

  • expires: 过期时间
  • max-age: 最大存活时间
  • domain: 域名
  • path: 路径
  • secure: 安全标志
  • HttpOnly: 防止XSS
  • SameSite: 防止CSRF

5. 如何选择存储方式?

  • Cookie: 会话管理、个性化
  • LocalStorage: 长期存储、用户设置
  • SessionStorage: 临时存储、表单数据
  • IndexedDB: 大数据、离线应用

通过理解浏览器存储机制,可以更好地管理应用数据和优化用户体验。

好好学习,天天向上