javascript
examples
examples.js⚡javascript
/**
* ========================================
* 11.1 localStorage and sessionStorage - Examples
* ========================================
*
* These examples demonstrate web storage APIs.
* Run in browser console for best results.
*/
/**
* ========================================
* EXAMPLE 1: Basic localStorage Operations
* ========================================
*/
console.log('--- Example 1: Basic localStorage Operations ---');
// Store values
localStorage.setItem('username', 'john_doe');
localStorage.setItem('theme', 'dark');
localStorage.setItem('fontSize', '16');
// Retrieve values
console.log('Username:', localStorage.getItem('username'));
console.log('Theme:', localStorage.getItem('theme'));
console.log('Font size:', localStorage.getItem('fontSize'));
// Check for non-existent key
console.log('Missing key:', localStorage.getItem('nonexistent')); // null
// Count items
console.log('Total items:', localStorage.length);
// Get key by index
console.log('First key:', localStorage.key(0));
// Remove specific item
localStorage.removeItem('fontSize');
console.log('After removal:', localStorage.getItem('fontSize')); // null
// Clean up example data
localStorage.removeItem('username');
localStorage.removeItem('theme');
/**
* ========================================
* EXAMPLE 2: Basic sessionStorage Operations
* ========================================
*/
console.log('\n--- Example 2: Basic sessionStorage Operations ---');
// Session storage works the same way
sessionStorage.setItem('sessionId', 'abc123');
sessionStorage.setItem('tempData', 'This will be gone when tab closes');
console.log('Session ID:', sessionStorage.getItem('sessionId'));
console.log('Temp data:', sessionStorage.getItem('tempData'));
// Clear session storage
sessionStorage.clear();
console.log('After clear:', sessionStorage.length);
/**
* ========================================
* EXAMPLE 3: Storing Objects with JSON
* ========================================
*/
console.log('\n--- Example 3: Storing Objects with JSON ---');
const user = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
preferences: {
theme: 'dark',
notifications: true,
language: 'en',
},
};
// Store object
localStorage.setItem('user', JSON.stringify(user));
console.log('Stored user object');
// Retrieve and parse
const savedUser = JSON.parse(localStorage.getItem('user'));
console.log('Retrieved user:', savedUser);
console.log('User name:', savedUser.name);
console.log('User theme:', savedUser.preferences.theme);
// Clean up
localStorage.removeItem('user');
/**
* ========================================
* EXAMPLE 4: Storing Arrays
* ========================================
*/
console.log('\n--- Example 4: Storing Arrays ---');
const todos = [
{ id: 1, text: 'Learn JavaScript', completed: true },
{ id: 2, text: 'Learn Web Storage', completed: false },
{ id: 3, text: 'Build a project', completed: false },
];
// Store array
localStorage.setItem('todos', JSON.stringify(todos));
// Retrieve array
const savedTodos = JSON.parse(localStorage.getItem('todos'));
console.log('Retrieved todos:', savedTodos);
// Modify and save back
savedTodos[1].completed = true;
localStorage.setItem('todos', JSON.stringify(savedTodos));
console.log('Updated todos:', JSON.parse(localStorage.getItem('todos')));
// Clean up
localStorage.removeItem('todos');
/**
* ========================================
* EXAMPLE 5: Type Conversion Issues
* ========================================
*/
console.log('\n--- Example 5: Type Conversion Issues ---');
// Numbers become strings
localStorage.setItem('count', 42);
const count = localStorage.getItem('count');
console.log('Count value:', count);
console.log('Count type:', typeof count); // "string"
console.log('Count + 1 (wrong):', count + 1); // "421"
console.log('Count + 1 (correct):', Number(count) + 1); // 43
// Booleans become strings
localStorage.setItem('isActive', true);
const isActive = localStorage.getItem('isActive');
console.log('isActive value:', isActive);
console.log('isActive type:', typeof isActive); // "string"
console.log('isActive === true:', isActive === true); // false!
console.log('isActive === "true":', isActive === 'true'); // true
// Fix: Use JSON
localStorage.setItem('countJSON', JSON.stringify(42));
localStorage.setItem('isActiveJSON', JSON.stringify(true));
console.log('JSON count:', JSON.parse(localStorage.getItem('countJSON'))); // 42 (number)
console.log('JSON isActive:', JSON.parse(localStorage.getItem('isActiveJSON'))); // true (boolean)
// Clean up
['count', 'isActive', 'countJSON', 'isActiveJSON'].forEach((key) => {
localStorage.removeItem(key);
});
/**
* ========================================
* EXAMPLE 6: Storage Helper Class
* ========================================
*/
console.log('\n--- Example 6: Storage Helper Class ---');
class Storage {
constructor(prefix = 'app_') {
this.prefix = prefix;
}
_getKey(key) {
return `${this.prefix}${key}`;
}
set(key, value) {
const data = JSON.stringify(value);
localStorage.setItem(this._getKey(key), data);
}
get(key, defaultValue = null) {
const data = localStorage.getItem(this._getKey(key));
if (data === null) return defaultValue;
try {
return JSON.parse(data);
} catch {
return data;
}
}
remove(key) {
localStorage.removeItem(this._getKey(key));
}
has(key) {
return localStorage.getItem(this._getKey(key)) !== null;
}
clear() {
// Only clear items with our prefix
const keysToRemove = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith(this.prefix)) {
keysToRemove.push(key);
}
}
keysToRemove.forEach((key) => localStorage.removeItem(key));
}
}
// Usage
const storage = new Storage('myApp_');
storage.set('user', { name: 'John', age: 30 });
storage.set('settings', { theme: 'dark', fontSize: 16 });
storage.set('isLoggedIn', true);
console.log('User:', storage.get('user'));
console.log('Settings:', storage.get('settings'));
console.log('Is logged in:', storage.get('isLoggedIn'));
console.log('Missing key:', storage.get('missing', 'default'));
console.log('Has user:', storage.has('user'));
// Clean up
storage.clear();
/**
* ========================================
* EXAMPLE 7: Storage with Expiration
* ========================================
*/
console.log('\n--- Example 7: Storage with Expiration ---');
class ExpiringStorage {
static set(key, value, ttlSeconds) {
const item = {
value: value,
expiry: Date.now() + ttlSeconds * 1000,
createdAt: Date.now(),
};
localStorage.setItem(key, JSON.stringify(item));
}
static get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
try {
const item = JSON.parse(itemStr);
if (Date.now() > item.expiry) {
localStorage.removeItem(key);
console.log(`Key "${key}" expired and was removed`);
return null;
}
return item.value;
} catch {
return null;
}
}
static getTimeRemaining(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
try {
const item = JSON.parse(itemStr);
const remaining = item.expiry - Date.now();
return remaining > 0 ? remaining : 0;
} catch {
return null;
}
}
}
// Store item that expires in 5 seconds
ExpiringStorage.set('tempToken', 'abc123', 5);
console.log('Token:', ExpiringStorage.get('tempToken'));
console.log(
'Time remaining:',
ExpiringStorage.getTimeRemaining('tempToken'),
'ms'
);
// Demonstrate expiration (uncomment to test)
// setTimeout(() => {
// console.log('After 6 seconds:', ExpiringStorage.get('tempToken')); // null
// }, 6000);
/**
* ========================================
* EXAMPLE 8: Checking Storage Availability
* ========================================
*/
console.log('\n--- Example 8: Checking Storage Availability ---');
function isStorageAvailable(type) {
let storage;
try {
storage = window[type];
const testKey = '__storage_test__';
storage.setItem(testKey, testKey);
storage.removeItem(testKey);
return true;
} catch (e) {
return (
e instanceof DOMException &&
// Everything except Firefox
(e.code === 22 ||
// Firefox
e.code === 1014 ||
// Test name field too, because code might not be present
e.name === 'QuotaExceededError' ||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// Acknowledge QuotaExceededError only if there's something already stored
storage &&
storage.length !== 0
);
}
}
console.log('localStorage available:', isStorageAvailable('localStorage'));
console.log('sessionStorage available:', isStorageAvailable('sessionStorage'));
/**
* ========================================
* EXAMPLE 9: Storage Size Calculator
* ========================================
*/
console.log('\n--- Example 9: Storage Size Calculator ---');
function getStorageSize(storage = localStorage) {
let total = 0;
for (let i = 0; i < storage.length; i++) {
const key = storage.key(i);
const value = storage.getItem(key);
// Each character is 2 bytes in JavaScript (UTF-16)
total += (key.length + value.length) * 2;
}
return {
bytes: total,
kilobytes: (total / 1024).toFixed(2),
megabytes: (total / (1024 * 1024)).toFixed(4),
};
}
// Add some test data
localStorage.setItem('sizeTest1', 'Hello World');
localStorage.setItem('sizeTest2', JSON.stringify({ data: 'x'.repeat(1000) }));
const size = getStorageSize();
console.log('Storage size:', size);
// Clean up
localStorage.removeItem('sizeTest1');
localStorage.removeItem('sizeTest2');
/**
* ========================================
* EXAMPLE 10: Iterating Over Storage
* ========================================
*/
console.log('\n--- Example 10: Iterating Over Storage ---');
// Add test data
localStorage.setItem('iter_name', 'John');
localStorage.setItem('iter_age', '30');
localStorage.setItem('iter_city', 'NYC');
// Method 1: Using key() and length
console.log('Method 1 - key() and length:');
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith('iter_')) {
console.log(` ${key}: ${localStorage.getItem(key)}`);
}
}
// Method 2: Using Object.keys()
console.log('Method 2 - Object.keys():');
Object.keys(localStorage)
.filter((key) => key.startsWith('iter_'))
.forEach((key) => {
console.log(` ${key}: ${localStorage.getItem(key)}`);
});
// Method 3: Get all as object
console.log('Method 3 - As object:');
const allData = {};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith('iter_')) {
allData[key] = localStorage.getItem(key);
}
}
console.log(' ', allData);
// Clean up
['iter_name', 'iter_age', 'iter_city'].forEach((key) =>
localStorage.removeItem(key)
);
/**
* ========================================
* EXAMPLE 11: Storage Event Listener
* ========================================
*/
console.log('\n--- Example 11: Storage Event Listener ---');
// This event fires when storage changes in ANOTHER tab
function handleStorageChange(event) {
console.log('Storage changed!');
console.log('Key:', event.key);
console.log('Old value:', event.oldValue);
console.log('New value:', event.newValue);
console.log('URL:', event.url);
console.log(
'Storage area:',
event.storageArea === localStorage ? 'localStorage' : 'sessionStorage'
);
}
// Add listener
window.addEventListener('storage', handleStorageChange);
console.log('Storage event listener added.');
console.log(
'Open this page in another tab and modify localStorage to see events.'
);
// To test:
// 1. Open this page in two tabs
// 2. In one tab's console, run: localStorage.setItem('test', 'hello')
// 3. The other tab will log the storage event
/**
* ========================================
* EXAMPLE 12: Todo List with Storage
* ========================================
*/
console.log('\n--- Example 12: Todo List with Storage ---');
class TodoStorage {
constructor(storageKey = 'todos') {
this.storageKey = storageKey;
}
_load() {
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : [];
}
_save(todos) {
localStorage.setItem(this.storageKey, JSON.stringify(todos));
}
getAll() {
return this._load();
}
add(text) {
const todos = this._load();
const newTodo = {
id: Date.now(),
text: text,
completed: false,
createdAt: new Date().toISOString(),
};
todos.push(newTodo);
this._save(todos);
return newTodo;
}
toggle(id) {
const todos = this._load();
const todo = todos.find((t) => t.id === id);
if (todo) {
todo.completed = !todo.completed;
this._save(todos);
}
return todo;
}
remove(id) {
const todos = this._load();
const filtered = todos.filter((t) => t.id !== id);
this._save(filtered);
return filtered;
}
clear() {
this._save([]);
}
}
// Usage
const todoStore = new TodoStorage('demo_todos');
todoStore.clear();
console.log('Adding todos...');
const todo1 = todoStore.add('Learn localStorage');
const todo2 = todoStore.add('Build a project');
const todo3 = todoStore.add('Practice daily');
console.log('All todos:', todoStore.getAll());
console.log('Toggling first todo...');
todoStore.toggle(todo1.id);
console.log('After toggle:', todoStore.getAll());
console.log('Removing second todo...');
todoStore.remove(todo2.id);
console.log('After remove:', todoStore.getAll());
// Clean up
localStorage.removeItem('demo_todos');
/**
* ========================================
* EXAMPLE 13: User Preferences Manager
* ========================================
*/
console.log('\n--- Example 13: User Preferences Manager ---');
class PreferencesManager {
constructor() {
this.storageKey = 'userPreferences';
this.defaults = {
theme: 'light',
fontSize: 16,
language: 'en',
notifications: true,
autoSave: true,
};
}
get() {
const saved = localStorage.getItem(this.storageKey);
if (!saved) return { ...this.defaults };
return { ...this.defaults, ...JSON.parse(saved) };
}
set(key, value) {
const prefs = this.get();
prefs[key] = value;
localStorage.setItem(this.storageKey, JSON.stringify(prefs));
return prefs;
}
setMultiple(updates) {
const prefs = this.get();
Object.assign(prefs, updates);
localStorage.setItem(this.storageKey, JSON.stringify(prefs));
return prefs;
}
reset() {
localStorage.removeItem(this.storageKey);
return this.defaults;
}
}
// Usage
const prefs = new PreferencesManager();
console.log('Default preferences:', prefs.get());
prefs.set('theme', 'dark');
console.log('After setting theme:', prefs.get());
prefs.setMultiple({ fontSize: 18, language: 'es' });
console.log('After bulk update:', prefs.get());
prefs.reset();
console.log('After reset:', prefs.get());
/**
* ========================================
* EXAMPLE 14: Session-based Form Draft
* ========================================
*/
console.log('\n--- Example 14: Session-based Form Draft ---');
class FormDraft {
constructor(formId) {
this.formId = formId;
this.storageKey = `formDraft_${formId}`;
}
save(formData) {
const draft = {
data: formData,
savedAt: new Date().toISOString(),
};
sessionStorage.setItem(this.storageKey, JSON.stringify(draft));
console.log('Draft saved at', draft.savedAt);
}
load() {
const saved = sessionStorage.getItem(this.storageKey);
if (!saved) return null;
const draft = JSON.parse(saved);
console.log('Draft loaded from', draft.savedAt);
return draft.data;
}
clear() {
sessionStorage.removeItem(this.storageKey);
console.log('Draft cleared');
}
hasDraft() {
return sessionStorage.getItem(this.storageKey) !== null;
}
}
// Usage
const contactFormDraft = new FormDraft('contactForm');
// Simulate saving form data
contactFormDraft.save({
name: 'John Doe',
email: 'john@example.com',
message: 'Hello, I would like to...',
});
// Check if draft exists
console.log('Has draft:', contactFormDraft.hasDraft());
// Load draft
const savedData = contactFormDraft.load();
console.log('Loaded draft:', savedData);
// Clear draft (e.g., after successful submit)
contactFormDraft.clear();
/**
* ========================================
* EXAMPLE 15: Cross-Tab State Sync
* ========================================
*/
console.log('\n--- Example 15: Cross-Tab State Sync ---');
class CrossTabSync {
constructor(channelName) {
this.channelName = channelName;
this.listeners = [];
// Listen for storage events from other tabs
window.addEventListener('storage', (e) => {
if (e.key === `sync_${this.channelName}`) {
const message = JSON.parse(e.newValue);
this._notifyListeners(message);
}
});
}
broadcast(message) {
const data = {
...message,
timestamp: Date.now(),
tabId: this._getTabId(),
};
// Store the message (triggers storage event in other tabs)
localStorage.setItem(`sync_${this.channelName}`, JSON.stringify(data));
// Clean up after a short delay
setTimeout(() => {
localStorage.removeItem(`sync_${this.channelName}`);
}, 100);
}
onMessage(callback) {
this.listeners.push(callback);
}
_notifyListeners(message) {
this.listeners.forEach((callback) => callback(message));
}
_getTabId() {
if (!sessionStorage.getItem('tabId')) {
sessionStorage.setItem('tabId', Math.random().toString(36).substr(2, 9));
}
return sessionStorage.getItem('tabId');
}
}
// Usage
const sync = new CrossTabSync('app-events');
sync.onMessage((message) => {
console.log('Received from another tab:', message);
});
// To test:
// Open page in multiple tabs
// In one tab: sync.broadcast({ type: 'logout' })
// Other tabs will receive the message
console.log('Cross-tab sync initialized.');
console.log('Open in another tab and run: sync.broadcast({ type: "hello" })');
/**
* ========================================
* Running Examples Summary
* ========================================
*/
console.log('\n========================================');
console.log('localStorage and sessionStorage Examples');
console.log('========================================');
console.log('All examples completed!');
console.log('');
console.log('Key classes available:');
console.log('- Storage: Namespaced storage with JSON support');
console.log('- ExpiringStorage: Storage with TTL');
console.log('- TodoStorage: Todo list with persistence');
console.log('- PreferencesManager: User preferences handler');
console.log('- FormDraft: Session-based form draft');
console.log('- CrossTabSync: Cross-tab communication');