दिन 15: localStorage, sessionStorage और JSON
✅ आज आप सीखेंगे
- localStorage बनाम sessionStorage बनाम cookies बनाम IndexedDB
- setItem, getItem, removeItem – सिर्फ़ strings
- JSON से objects और arrays save करना
- Defaults, versioning और try/catch वाला सुरक्षित storage helper
- असली उपयोग: cart, theme, form drafts – और क्या कभी न रखें
🏢 असली दुनिया में
एक customer cart में 4 मिठाइयाँ डालती है, phone आता है, tab बंद करती है – और लौटने पर cart ख़ाली मिलता है। वह चली जाती है। Online shops में बार-बार देखा गया है कि याद रखा cart ख़रीदारों का अच्छा हिस्सा वापस लाता है। Cart, चुनी theme और आधा लिखा message याद रखना – सब Web Storage से होता है।
Browser data कहाँ रख सकता है?
| Storage | अवधि | Size | Server को जाता है? | कब |
|---|---|---|---|---|
| localStorage ⭐ | Delete होने तक | ~5 MB प्रति site | नहीं | Cart, theme, preferences, drafts |
| sessionStorage | Tab बंद होने तक | ~5 MB | नहीं | एक-बार wizard steps, tab की अस्थायी state |
| Cookies | Expiry तक | ~4 KB हर एक | हाँ, हर request के साथ | Login sessions (HttpOnly, server लगाता है) |
| IndexedDB | Delete होने तक | बड़ा (सैकड़ों MB) | नहीं | Offline apps, बड़ा data, files |
API: strings अंदर, strings बाहर
// Node.js has no localStorage, so this demo creates a tiny stand-in.
// In the browser, delete these 7 lines – localStorage already exists.
const localStorage = (() => {
const data = new Map();
return { getItem: k => (data.has(k) ? data.get(k) : null), setItem: (k, v) => data.set(k, String(v)),
removeItem: k => data.delete(k), clear: () => data.clear(), get length() { return data.size; },
key: i => [...data.keys()][i] ?? null };
})();
localStorage.setItem('theme', 'dark');
localStorage.setItem('visits', 3); // stored as the STRING "3"
console.log(localStorage.getItem('theme'));
console.log(typeof localStorage.getItem('visits'), Number(localStorage.getItem('visits')) + 1);
console.log(localStorage.getItem('missing')); // null when not found
localStorage.setItem('cart', { id: 1, qty: 2 }); // ❌ objects become "[object Object]"
console.log(localStorage.getItem('cart'));
localStorage.setItem('cart', JSON.stringify([{ id: 1, qty: 2 }])); // ✅
const cart = JSON.parse(localStorage.getItem('cart'));
console.log(cart[0].qty, Array.isArray(cart));
localStorage.removeItem('theme');
console.log(localStorage.length, 'keys left');Safari private mode, भरा quota, बंद cookies या sandboxed frame में localStorage error throw करता है। एक uncaught error पूरी script रोक देती है – इसलिए storage access हमेशा try…catch में रखें।
सुरक्षित, दोबारा उपयोगी storage helper
// Node.js has no localStorage, so this demo creates a tiny stand-in.
// In the browser, delete these 7 lines – localStorage already exists.
const localStorage = (() => {
const data = new Map();
return { getItem: k => (data.has(k) ? data.get(k) : null), setItem: (k, v) => data.set(k, String(v)),
removeItem: k => data.delete(k), clear: () => data.clear(), get length() { return data.size; },
key: i => [...data.keys()][i] ?? null };
})();
const store = {
get(key, fallback) {
try {
const raw = localStorage.getItem(key);
return raw === null ? fallback : JSON.parse(raw);
} catch (err) {
return fallback; // corrupted JSON or storage blocked
}
},
set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch (err) {
return false; // quota full or blocked
}
},
remove(key) {
try { localStorage.removeItem(key); } catch (err) { /* ignore */ }
},
};
store.set('ss-cart', { version: 2, items: [{ id: 1, qty: 2 }, { id: 4, qty: 1 }] });
console.log(store.get('ss-cart', { version: 2, items: [] }).items.length, 'items');
console.log(store.get('ss-theme', 'light')); // default when missing
localStorage.setItem('broken', '{not json');
console.log(store.get('broken', 'safe default'));Saved data का versioning
// Node.js has no localStorage, so this demo creates a tiny stand-in.
// In the browser, delete these 7 lines – localStorage already exists.
const localStorage = (() => {
const data = new Map();
return { getItem: k => (data.has(k) ? data.get(k) : null), setItem: (k, v) => data.set(k, String(v)),
removeItem: k => data.delete(k), clear: () => data.clear(), get length() { return data.size; },
key: i => [...data.keys()][i] ?? null };
})();
// Old site (v1) saved: { "1": 2, "4": 1 } (id → qty)
localStorage.setItem('ss-cart', JSON.stringify({ 1: 2, 4: 1 }));
function loadCart() {
let saved;
try { saved = JSON.parse(localStorage.getItem('ss-cart')); } catch (e) { saved = null; }
if (!saved) return { version: 2, items: [] };
if (saved.version === 2) return saved;
// migrate v1 → v2 so returning customers keep their cart
const items = Object.entries(saved).map(([id, qty]) => ({ id: Number(id), qty }));
const migrated = { version: 2, items };
localStorage.setItem('ss-cart', JSON.stringify(migrated));
return migrated;
}
console.log(JSON.stringify(loadCart()));ss-cart, ss-theme जैसे नाम लें। एक domain की हर script एक ही localStorage साझा करती है – prefixes plugins या subfolders के दूसरे apps से टकराव रोकते हैं।
असली task: theme + draft autosave
<button id="theme">🌓 Toggle theme</button>
<p><label for="msg">Message for Sharma Sweets</label><br>
<textarea id="msg" rows="3" cols="40" placeholder="Type – it is saved as you go"></textarea></p>
<p id="status" role="status"></p>
<script>
// safe helpers (same as above, shortened)
const store = {
get(k, d) { try { const r = localStorage.getItem(k); return r === null ? d : JSON.parse(r); } catch (e) { return d; } },
set(k, v) { try { localStorage.setItem(k, JSON.stringify(v)); return true; } catch (e) { return false; } },
};
const status = document.querySelector('#status');
// theme
let theme = store.get('ss-theme', 'light');
const apply = () => { document.body.style.background = theme === 'dark' ? '#111827' : '#fff'; document.body.style.color = theme === 'dark' ? '#e5e7eb' : '#111827'; };
apply();
document.querySelector('#theme').addEventListener('click', () => {
theme = theme === 'dark' ? 'light' : 'dark';
const saved = store.set('ss-theme', theme);
apply();
status.textContent = saved ? 'Theme saved ✅' : 'Theme changed (saving is blocked in this preview – works on a real page)';
});
// draft autosave
const msg = document.querySelector('#msg');
msg.value = store.get('ss-draft', '');
msg.addEventListener('input', () => {
const ok = store.set('ss-draft', msg.value);
status.textContent = ok ? 'Draft saved ✓' : 'Draft kept in memory only (storage blocked here)';
});
</script>क्या कभी नहीं रखना चाहिए
localStorage में ठीक
- Cart items और quantities
- Theme, भाषा, आख़िरी filter
- Form drafts (संवेदनशील नहीं)
- हाल में देखे products
localStorage में कभी नहीं
- Passwords या OTPs
- Card numbers, UPI PINs, Aadhaar
- लंबे समय के login tokens (कोई भी script पढ़ सकती है – XSS)
- Billing में इस्तेमाल prices – server पर हमेशा दोबारा गिनें
Bonus: tabs के बीच sync
// Fires in OTHER tabs of the same site when localStorage changes
window.addEventListener('storage', (e) => {
if (e.key === 'ss-cart') {
cart = JSON.parse(e.newValue || '{"version":2,"items":[]}');
renderCartBadge(); // the cart count updates in every open tab
}
});🏅 आज के Job Skills
Practice tasks
🏋️ Practice – ख़ुद करें
Solution देखें
// Node.js has no localStorage, so this demo creates a tiny stand-in.
// In the browser, delete these 7 lines – localStorage already exists.
const localStorage = (() => {
const data = new Map();
return { getItem: k => (data.has(k) ? data.get(k) : null), setItem: (k, v) => data.set(k, String(v)),
removeItem: k => data.delete(k), clear: () => data.clear(), get length() { return data.size; },
key: i => [...data.keys()][i] ?? null };
})();
function visit() {
const n = Number(localStorage.getItem('ss-visits') || 0) + 1;
localStorage.setItem('ss-visits', n);
return n >= 3 ? `Welcome back! Visit #${n} – here is 5% off 🎁` : `Visit #${n}`;
}
console.log(visit());
console.log(visit());
console.log(visit());Solution देखें
// Node.js has no localStorage, so this demo creates a tiny stand-in.
// In the browser, delete these 7 lines – localStorage already exists.
const localStorage = (() => {
const data = new Map();
return { getItem: k => (data.has(k) ? data.get(k) : null), setItem: (k, v) => data.set(k, String(v)),
removeItem: k => data.delete(k), clear: () => data.clear(), get length() { return data.size; },
key: i => [...data.keys()][i] ?? null };
})();
function remember(id) {
let list = JSON.parse(localStorage.getItem('ss-recent') || '[]');
list = [id, ...list.filter(x => x !== id)].slice(0, 5);
localStorage.setItem('ss-recent', JSON.stringify(list));
return list;
}
[3, 1, 4, 1, 5, 9, 2].forEach(id => remember(id));
console.log(JSON.parse(localStorage.getItem('ss-recent')));Quick quiz
🧠 Quick Quiz – ख़ुद को जाँचें
Interview corner
💼 Interview Corner
localStorage बनाम sessionStorage बनाम cookies?
localStorage origin के अनुसार साफ़ होने तक रहता है; sessionStorage tab session तक; दोनों ~5 MB, synchronous, server को कभी नहीं जाते। Cookies छोटी, हर request के साथ जाती हैं, HttpOnly/Secure/SameSite हो सकती हैं – server sessions के लिए सही।
JWTs को localStorage में रखना जोखिम भरा क्यों?
Page पर चलने वाला कोई भी JavaScript – injected XSS code या compromised third-party script समेत – उसे पढ़कर attacker को भेज सकता है। HttpOnly, Secure, SameSite cookies JavaScript नहीं पढ़ सकता।
सारांश
- localStorage टिकता है, sessionStorage tab तक; दोनों strings रखते हैं।
- Objects save करने को JSON.stringify, पढ़ने को JSON.parse।
- Access try…catch में, defaults, prefixes और versions के साथ।
- Secrets कभी न रखें; prices server पर दोबारा गिनें।
Day 16: scope, hoisting और closures – interviewers के पसंदीदा concepts जो counters, caches और private data चलाते हैं।
