التخزين المحلي في JavaScript: localStorage
كل ما بنيته حتى الآن ينسى كل شيء عند تحديث الصفحة: العدّاد يعود إلى الصفر، والقائمة تفرغ. السبب أن المتغيرات تعيش في الذاكرة ما دامت الصفحة مفتوحة فقط. في هذا الدرس ستتعلم التخزين المحلي (localStorage)، وبه تحفظ بيانات صغيرة في متصفح المستخدم فتبقى بعد التحديث وبعد إغلاق المتصفح.
ما هو localStorage؟
Section titled “ما هو localStorage؟”هو مخزن صغير يعطيه المتصفح لكل موقع، يحفظ فيه أزواجاً من مفتاح وقيمة، مثل كائن بسيط.
تخيّل خزانة الأمانات في النادي: لكل عضو خزانة باسمه، يضع فيها أغراضه ويغادر، وعندما يعود في يوم آخر يجدها كما تركها. ولا يستطيع عضو أن يفتح خزانة غيره. وهكذا المواقع: لكل موقع مخزنه، ولا يقرأ موقع مخزن موقع آخر.
والبيانات تُحفظ على جهاز المستخدم نفسه، ولا تُرسل إلى أي خادم.
الحفظ والقراءة
Section titled “الحفظ والقراءة”localStorage.setItem("username", "سارة");
const savedName = localStorage.getItem("username");console.log(savedName);
console.log(localStorage.getItem("age"));سارةnullsetItem(المفتاح, القيمة): تحفظ القيمة. وإذا كان المفتاح موجوداً استبدلت قيمته.getItem(المفتاح): تُرجع القيمة المحفوظة، أوnullإذا لم يُحفظ شيء بهذا المفتاح.
حدّث الصفحة الآن واقرأ username من جديد: ستجد القيمة ما زالت موجودة.
localStorage.setItem("color", "blue");localStorage.setItem("lang", "ar");console.log(localStorage.length);
localStorage.removeItem("color");console.log(localStorage.getItem("color"));
localStorage.clear();console.log(localStorage.length);3null0removeItem(المفتاح): تحذف مفتاحاً واحداً.clear(): تحذف كل ما حفظه موقعك.length: عدد المفاتيح المحفوظة.
لماذا كان العدد 3 وليس 2؟ لأن المفتاح username من المثال السابق ما زال محفوظاً. وهذه هي الفكرة كلها: البيانات لا تختفي حتى تحذفها أنت.
كل شيء يُحفظ نصاً
Section titled “كل شيء يُحفظ نصاً”هذه أهم قاعدة في الدرس: localStorage يخزّن نصوصاً فقط. أي قيمة تعطيها له يحوّلها إلى نص أولاً.
localStorage.setItem("score", 50);
const score = localStorage.getItem("score");console.log(typeof score);console.log(score + 1);console.log(Number(score) + 1);string50151حفظنا الرقم 50 فعاد النص "50"، وعندما جمعنا عليه 1 التصق الرقمان. الحل أن تحوّل القيمة بـ Number بعد قراءتها.
حفظ الكائنات والمصفوفات
Section titled “حفظ الكائنات والمصفوفات”وماذا لو حفظت كائناً مباشرة؟
const settings = { theme: "dark", fontSize: 18 };
localStorage.setItem("settings", settings);console.log(localStorage.getItem("settings"));[object Object]ضاعت البيانات! تحويل الكائن إلى نص بالطريقة العادية يعطي هذه العبارة عديمة الفائدة. والحل تعرفه من درس JSON: حوّل الكائن بـ JSON.stringify قبل الحفظ، وأعده بـ JSON.parse بعد القراءة.
localStorage.setItem("settings", JSON.stringify(settings));
const savedSettings = JSON.parse(localStorage.getItem("settings"));console.log(savedSettings.theme);console.log(savedSettings.fontSize + 2);dark20عاد الكائن كاملاً، والرقم عاد رقماً.
نمط جاهز: دالة تحمّل ودالة تحفظ
Section titled “نمط جاهز: دالة تحمّل ودالة تحفظ”في المشاريع نجمع التعامل مع المخزن في دالتين، ونستخدمهما في كل مكان:
function loadTasks() { const text = localStorage.getItem("tasks"); if (text === null) { return []; } return JSON.parse(text);}
function saveTasks(tasks) { localStorage.setItem("tasks", JSON.stringify(tasks));}
const tasks = loadTasks();console.log(tasks.length);
tasks.push("مذاكرة الدرس");saveTasks(tasks);
console.log(loadTasks());0[ 'مذاكرة الدرس' ]انتبه إلى الشرط text === null: في أول زيارة لا يوجد شيء محفوظ، فنُرجع مصفوفة فارغة ليعمل باقي الكود بلا مشاكل. نسيان هذه الحالة من أشهر أخطاء المبتدئين.
مثال عملي: عدّاد الزيارات
Section titled “مثال عملي: عدّاد الزيارات”<p id="visits"></p>
<script> const count = Number(localStorage.getItem("visits")) + 1; localStorage.setItem("visits", count);
document.querySelector("#visits").textContent = `زرت هذه الصفحة ${count} مرة`;</script>في أول زيارة تُرجع getItem القيمة null، و Number(null) تساوي 0، فيصبح العدد 1. ومع كل تحديث للصفحة يزيد العدد واحداً، حتى لو أغلقت المتصفح وعدت في الغد.
أين ترى البيانات المحفوظة؟
Section titled “أين ترى البيانات المحفوظة؟”افتح أدوات المطوّر بـ F12، ثم:
- في Chrome و Edge: تبويب Application، ثم Local Storage من القائمة الجانبية.
- في Firefox: تبويب Storage، ثم Local Storage.
سترى جدولاً بكل المفاتيح والقيم، وتستطيع تعديلها وحذفها بيدك. وهذا مفيد جداً عند البحث عن خطأ.
sessionStorage: مخزن مؤقت
Section titled “sessionStorage: مخزن مؤقت”للمتصفح مخزن آخر اسمه sessionStorage، وله الدوال نفسها تماماً. الفرق الوحيد في العمر:
| المخزن | متى تُمسح البيانات؟ |
|---|---|
localStorage |
لا تُمسح حتى تحذفها أنت أو المستخدم |
sessionStorage |
عند إغلاق التبويب |
استخدم sessionStorage لما تحتاجه خلال الزيارة الحالية فقط، مثل الخطوة التي وصل إليها المستخدم في نموذج طويل.
حدود يجب أن تعرفها
Section titled “حدود يجب أن تعرفها”- المساحة صغيرة: حوالي 5 ميجابايت للموقع. تكفي للإعدادات والقوائم، ولا تصلح للصور والملفات.
- على هذا الجهاز فقط: ما تحفظه في متصفح الحاسوب لا يظهر على هاتفك.
- المستخدم قد يمسحه: إذا مسح بيانات التصفح ضاع المخزن، فلا تجعله المكان الوحيد لبيانات مهمة.
جرّب بنفسك
Section titled “جرّب بنفسك”أنشئ ملفاً باسم theme.html، واكتب فيه صفحة تتذكر هل اختار المستخدم الوضع الليلي:
<!DOCTYPE html><html lang="ar" dir="rtl"><head> <meta charset="UTF-8"> <title>الوضع الليلي</title> <style> body.dark { background: #171b2e; color: #eef0f8; } </style></head><body> <h1>مرحباً بك</h1> <button id="toggle">بدّل الوضع</button>
<script> if (localStorage.getItem("theme") === "dark") { document.body.classList.add("dark"); }
document.querySelector("#toggle").addEventListener("click", () => { const isDark = document.body.classList.toggle("dark"); localStorage.setItem("theme", isDark ? "dark" : "light"); }); </script></body></html>الدالة classList.toggle تُرجع true إذا أضافت الكلاس و false إذا أزالته، فنعرف منها الوضع الحالي ونحفظه.
افتح الملف واضغط الزر ليصبح الوضع ليلياً، ثم حدّث الصفحة: يجب أن تبقى ليلية. بعد ذلك أضف عدّاداً يعرض كم مرة بدّل المستخدم الوضع، واحفظه هو أيضاً.
أخطاء شائعة
Section titled “أخطاء شائعة”- حفظ كائن أو مصفوفة بدون
JSON.stringify: تُحفظ العبارة[object Object]وتضيع البيانات. - نسيان أن القيمة نص:
getItem("score") + 1تلصق النصين. حوّل بـNumberأو بـJSON.parseأولاً. - تجاهل حالة
null: في أول زيارة لا توجد بيانات، فاستدعاء.lengthأو.pushعلىnullيوقف السكربت بخطأ.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ماذا يطبع الكود التالي؟ localStorage.setItem('n', 7); console.log(localStorage.getItem('n') + 3);
القيمة تُحفظ نصاً وتعود نصاً، فيصبح الجمع لصقاً لنصين: 73. للحصول على 10 استخدم Number.
سؤال
ما الطريقة الصحيحة لحفظ مصفوفة اسمها tasks؟
المخزن يقبل النصوص فقط، فنحوّل المصفوفة إلى نص JSON عند الحفظ، ونعيدها بـ JSON.parse عند القراءة.
الخلاصة
Section titled “الخلاصة”localStorageيحفظ بيانات صغيرة في متصفح المستخدم، وتبقى بعد التحديث والإغلاق.setItemللحفظ، وgetItemللقراءة، وremoveItemوclearللحذف.- كل القيم تُحفظ نصوصاً: استخدم
JSON.stringifyعند الحفظ وJSON.parseعند القراءة. getItemتُرجعnullفي أول زيارة، فجهّز قيمة افتراضية.- لا تحفظ فيه كلمات مرور ولا أي بيانات حساسة.