-
-
Notifications
You must be signed in to change notification settings - Fork 2
JavaScript Storage APIs
Mattscreative edited this page Feb 21, 2026
·
1 revision
JavaScript provides several ways to store data in the browser. Each has different use cases and characteristics.
localStorage stores data with no expiration time. Data persists even after closing the browser.
// Set item
localStorage.setItem('username', 'Alice');
localStorage.setItem('preferences', JSON.stringify({ theme: 'dark', lang: 'en' }));
// Get item
const username = localStorage.getItem('username');
const prefs = JSON.parse(localStorage.getItem('preferences'));
// Remove item
localStorage.removeItem('username');
// Clear all
localStorage.clear();
// Check if key exists
localStorage.getItem('username') !== null; // true/false// Length
console.log(localStorage.length); // Number of items
// Get key by index
console.log(localStorage.key(0)); // First key
// Iterate over all items
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(key, value);
}
// Using forEach (modern)
Object.keys(localStorage).forEach(key => {
console.log(key, localStorage.getItem(key));
});// Listen for changes in localStorage (on other tabs)
window.addEventListener('storage', (event) => {
console.log('Key changed:', event.key);
console.log('Old value:', event.oldValue);
console.log('New value:', event.newValue);
console.log('URL:', event.url);
});// Storage limits (approximately 5-10MB)
console.log('Approximate quota:', 5 * 1024 * 1024, 'bytes');
// Only stores strings
localStorage.setItem('number', 42); // Stored as "42"
localStorage.setItem('boolean', true); // Stored as "true"
localStorage.setItem('array', [1, 2, 3]); // Stored as "1,2,3"
// Solution: Use JSON
localStorage.setItem('data', JSON.stringify({
number: 42,
boolean: true,
array: [1, 2, 3]
}));sessionStorage stores data for one session (until the tab is closed).
// Same API as localStorage
sessionStorage.setItem('tempData', 'value');
const value = sessionStorage.getItem('tempData');
sessionStorage.removeItem('tempData');
sessionStorage.clear();
// Data is cleared when tab/window closes
sessionStorage.setItem('sessionData', 'This will be gone when tab closes');// Remember form progress during a session
function saveFormProgress(field, value) {
sessionStorage.setItem(`form_${field}`, value);
}
// Store sensitive data that shouldn't persist
sessionStorage.setItem('authToken', 'temporary-token');
// Temporary calculations
sessionStorage.setItem('calculation', JSON.stringify({ result: 42 }));IndexedDB is a powerful client-side database for storing large amounts of structured data.
// Open database
const request = indexedDB.open('MyDatabase', 1);
// Handle success
request.onsuccess = (event) => {
const db = event.target.result;
console.log('Database opened');
};
// Handle errors
request.onerror = (event) => {
console.error('Database error:', event.target.error);
};
// Handle upgrades (schema changes)
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Create object store
if (!db.objectStoreNames.contains('users')) {
const userStore = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
// Create indexes
userStore.createIndex('name', 'name', { unique: false });
userStore.createIndex('email', 'email', { unique: true });
}
};function addUser(user) {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
const addRequest = store.add(user);
addRequest.onsuccess = () => {
console.log('User added:', addRequest.result);
};
};
}
addUser({ name: 'Alice', email: 'alice@example.com', age: 25 });function getUser(id) {
return new Promise((resolve, reject) => {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readonly');
const store = transaction.objectStore('users');
const getRequest = store.get(id);
getRequest.onsuccess = () => {
resolve(getRequest.result);
};
getRequest.onerror = () => {
reject(getRequest.error);
};
};
});
}
// Get all users
function getAllUsers() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readonly');
const store = transaction.objectStore('users');
const getAllRequest = store.getAll();
getAllRequest.onsuccess = () => {
resolve(getAllRequest.result);
};
};
});
}function updateUser(id, updates) {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
// First get the user
const getRequest = store.get(id);
getRequest.onsuccess = () => {
const user = getRequest.result;
const updatedUser = { ...user, ...updates };
store.put(updatedUser);
};
};
}function deleteUser(id) {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
store.delete(id);
};
}
// Clear all users
function clearUsers() {
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
store.clear();
};
}class IndexedDBWrapper {
constructor(dbName, version, stores) {
this.dbName = dbName;
this.version = version;
this.stores = stores;
}
open() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onupgradeneeded = (event) => {
const db = event.target.result;
this.stores.forEach(store => {
if (!db.objectStoreNames.contains(store.name)) {
const objectStore = db.createObjectStore(store.name, store.options);
store.indexes?.forEach(index => {
objectStore.createIndex(index.name, index.keyPath, index.options);
});
}
});
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async get(storeName, key) {
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const request = store.get(key);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async getAll(storeName) {
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const request = store.getAll();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async add(storeName, data) {
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.add(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async put(storeName, data) {
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.put(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async delete(storeName, key) {
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.delete(key);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
}Cookies are small pieces of data sent between browser and server.
// Basic cookie
document.cookie = "username=Alice";
document.cookie = "theme=dark";
document.cookie = "session=abc123; max-age=3600"; // Expires in 1 hour
// With all options
document.cookie = "token=xyz789; " +
"expires=" + new Date(Date.now() + 86400000).toUTCString() + "; " +
"path=/; " +
"domain=example.com; " +
"secure; " +
"samesite=strict";// Get all cookies
console.log(document.cookie);
// Parse cookies
function getCookie(name) {
const nameEQ = name + "=";
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
cookie = cookie.trim();
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length);
}
}
return null;
}
console.log(getCookie('username'));
console.log(getCookie('theme'));// Delete by setting expiration to past
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";| Feature | localStorage | sessionStorage | IndexedDB | Cookies |
|---|---|---|---|---|
| Capacity | ~5-10MB | ~5-10MB | Large (50MB+) | ~4KB |
| Data Type | Strings only | Strings only | Any | Strings |
| Sync/Async | Sync | Sync | Async | Sync |
| Expiration | Never | Tab close | Manual | Manual |
| Server Access | No | No | No | Yes |
| Performance | Fast | Fast | Slower | Slow |
class ThemeSwitcher {
constructor() {
this.theme = localStorage.getItem('theme') || 'light';
this.applyTheme();
}
toggle() {
this.theme = this.theme === 'light' ? 'dark' : 'light';
this.applyTheme();
localStorage.setItem('theme', this.theme);
}
applyTheme() {
document.body.classList.remove('light', 'dark');
document.body.classList.add(this.theme);
}
}
const themeSwitcher = new ThemeSwitcher();class FormAutoSave {
constructor(formId, key) {
this.form = document.getElementById(formId);
this.key = key;
this.load();
this.setupListeners();
}
setupListeners() {
this.form.addEventListener('input', (e) => {
this.save();
});
}
save() {
const data = new FormData(this.form);
const obj = Object.fromEntries(data);
sessionStorage.setItem(this.key, JSON.stringify(obj));
}
load() {
const saved = sessionStorage.getItem(this.key);
if (saved) {
const data = JSON.parse(saved);
Object.entries(data).forEach(([key, value]) => {
const input = this.form.elements[key];
if (input) input.value = value;
});
}
}
clear() {
sessionStorage.removeItem(this.key);
}
}class OfflineStore {
constructor() {
this.dbName = 'OfflineApp';
this.dbVersion = 1;
}
async init() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.dbVersion);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('cache')) {
const cacheStore = db.createObjectStore('cache', { keyPath: 'url' });
cacheStore.createIndex('timestamp', 'timestamp', { unique: false });
}
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async cacheResponse(url, response) {
const data = {
url,
response: await response.clone().json(),
timestamp: Date.now()
};
const db = await this.init();
const tx = db.transaction('cache', 'readwrite');
tx.objectStore('cache').put(data);
}
async getCached(url) {
const db = await this.init();
return new Promise((resolve) => {
const tx = db.transaction('cache', 'readonly');
const request = tx.objectStore('cache').get(url);
request.onsuccess = () => resolve(request.result);
});
}
}class UserPreferences {
constructor() {
this.defaults = {
theme: 'light',
language: 'en',
notifications: true,
fontSize: 'medium'
};
this.prefs = this.load();
}
load() {
const saved = localStorage.getItem('preferences');
return saved ? { ...this.defaults, ...JSON.parse(saved) } : this.defaults;
}
save() {
localStorage.setItem('preferences', JSON.stringify(this.prefs));
}
get(key) {
return this.prefs[key];
}
set(key, value) {
this.prefs[key] = value;
this.save();
this.applyPreference(key, value);
}
applyPreference(key, value) {
switch (key) {
case 'theme':
document.body.classList.toggle('dark', value === 'dark');
break;
case 'fontSize':
document.body.style.fontSize = { small: '14px', medium: '16px', large: '18px' }[value];
break;
}
}
}