آموزش کار با Local Storage در جاوا اسکریپت

آموزش کار با Local Storage در جاوا اسکریپت

از دست دادن داده های واردشده در یک فرم، به ویژه با یک رفرش تصادفی یا بسته شدن مرورگر، می تواند تجربه ای بسیار ناخوشایند باشد. برای مقابله با این مشکل، توسعه دهندگان وب به سراغ راه حل های ذخیره سازی داده ها در سمت کلاینت می روند که جاوا اسکریپت ابزارهای قدرتمندی برای آن فراهم کرده است. در این میان، Local Storage به عنوان یک مکانیزم ذخیره سازی دائمی و کارآمد در مرورگر، نقش کلیدی ایفا می کند و اطمینان می دهد که اطلاعات حیاتی کاربر حتی پس از بسته شدن مرورگر نیز در دسترس باقی می مانند.

چرا به ذخیره سازی داده ها در مرورگر نیاز داریم؟

در دنیای امروز که سرعت و تجربه کاربری حرف اول را می زند، حفظ داده ها و تنظیمات کاربر بین جلسات مختلف مرورگر، دیگر یک امتیاز نیست، بلکه یک ضرورت است. این قابلیت به وب سایت ها اجازه می دهد تا وضعیت فرم ها، تنظیمات دلخواه کاربر مانند تم روشن/تاریک یا زبان انتخابی را به خاطر بسپارند و با کاهش نیاز به بارگذاری مجدد اطلاعات، سرعت و واکنش گرایی برنامه را افزایش دهند. این امر نه تنها باعث بهبود عملکرد و کاهش بار روی سرور می شود، بلکه به طور مستقیم به رضایت و وفاداری کاربر نیز منجر خواهد شد.

وب استانداردها، رابط برنامه نویسی Web Storage API را برای این منظور معرفی کرده اند که شامل دو بخش اصلی است: Local Storage و Session Storage. این دو API، راهی ساده و در عین حال قدرتمند برای ذخیره سازی جفت های کلید-مقدار (Key-Value) در مرورگر ارائه می دهند. در ادامه این گزارش، به طور خاص به قابلیت ها و نحوه کار با Local Storage در جاوا اسکریپت می پردازیم و جزئیات آن را بررسی می کنیم.

آموزش کار با Local Storage در جاوا اسکریپت

Local Storage در جاوا اسکریپت چیست؟

Local Storage در جاوا اسکریپت، یک مکانیزم ذخیره سازی اطلاعات در سمت کلاینت (مرورگر کاربر) است که به برنامه های وب اجازه می دهد تا داده ها را به صورت جفت های کلید-مقدار ذخیره کنند. تفاوت اصلی و برجسته Local Storage با سایر روش های ذخیره سازی در مرورگر، پایداری (Persistence) آن است. به این معنا که داده های ذخیره شده در Local Storage حتی پس از بسته شدن پنجره یا تب مرورگر و حتی راه اندازی مجدد کامپیوتر، همچنان در دسترس باقی می مانند و تاریخ انقضا ندارند.

این ویژگی آن را به ابزاری ایده آل برای ذخیره سازی اطلاعاتی تبدیل می کند که نیاز به ماندگاری طولانی مدت دارند، مانند تنظیمات شخصی سازی شده کاربر، وضعیت سبد خرید، یا توکن های احراز هویت. هر دامنه ای (Origin) به یک فضای Local Storage اختصاصی خود دسترسی دارد و نمی تواند به اطلاعات ذخیره شده توسط دامنه های دیگر دسترسی پیدا کند. این مکانیزم ذخیره سازی بخشی از شیء Window در جاوا اسکریپت است و از طریق Window.localStorage قابل دسترسی است.

Window.localStorage چیست؟

Window.localStorage یک ویژگی فقط خواندنی (read-only) در شیء Window است که به توسعه دهندگان اجازه می دهد تا به شیء Local Storage دسترسی پیدا کنند. شیء Window در جاوا اسکریپت، نمایانگر پنجره مرورگری است که سند HTML در آن بارگذاری شده است. این شیء یک دامنه سراسری دارد و متدها و ویژگی های مختلفی را برای تعامل با محیط مرورگر فراهم می کند.

Window.localStorage به طور خاص، یک رابط کاربری برای مدیریت داده های ذخیره شده در فضای Local Storage فراهم می کند. تمامی عملیات ذخیره، بازیابی، به روزرسانی و حذف داده ها در Local Storage از طریق متدهای موجود در این شیء انجام می شود. این دسترسی مستقیم و ساده، Local Storage را به یک ابزار قدرتمند و همه کاره برای توسعه دهندگان وب تبدیل کرده است تا بتوانند داده ها را فراتر از یک جلسه مرورگر واحد ذخیره و مدیریت کنند.

مقایسه Local Storage با Session Storage و Cookies

برای درک بهتر جایگاه Local Storage، مقایسه آن با دو مکانیزم دیگر ذخیره سازی در مرورگر، یعنی Session Storage و Cookies، ضروری است. هر یک از این ها ویژگی ها و موارد استفاده خاص خود را دارند.

مقایسه با Session Storage

Session Storage نیز مانند Local Storage، بخشی از Web Storage API است و برای ذخیره سازی جفت های کلید-مقدار در مرورگر استفاده می شود. اما تفاوت اصلی و حیاتی آن ها در ماندگاری داده ها است.

ویژگی Local Storage Session Storage
ماندگاری دائمی، حتی پس از بسته شدن مرورگر تا زمان بسته شدن تب یا پنجره مرورگر
دامنه (Scope) مشترک بین تمام تب ها و پنجره های یک دامنه محدود به تب/پنجره ای که آن را ایجاد کرده است
ظرفیت 5 تا 10 مگابایت (بسته به مرورگر) 5 تا 10 مگابایت (بسته به مرورگر)
ارسال به سرور خیر، فقط سمت کلاینت خیر، فقط سمت کلاینت
موارد استفاده متداول تنظیمات کاربر، سبد خرید، کش داده های آفلاین اطلاعات فرم، وضعیت صفحه، اطلاعات جلسه موقت

به طور خلاصه، اگر به داده هایی نیاز دارید که باید برای همیشه یا حداقل برای مدت طولانی در دسترس باشند (مثلاً ترجیحات کاربر)، Local Storage انتخاب بهتری است. اما اگر اطلاعات فقط برای مدت زمان یک جلسه خاص (مثلاً تکمیل یک فرم چند مرحله ای) ضروری هستند، Session Storage گزینه مناسب تری خواهد بود، چرا که با بسته شدن تب، آن داده ها نیز به طور خودکار پاک می شوند.

مقایسه با Cookies

کوکی ها (Cookies) قدیمی ترین و سنتی ترین روش برای ذخیره سازی داده های کوچک در مرورگر هستند و از ابتدای وب وجود داشته اند. اما تفاوت های عمده ای با Web Storage API (شامل Local Storage و Session Storage) دارند.

ویژگی Local Storage Cookies
ظرفیت 5 تا 10 مگابایت 4 کیلوبایت (برای هر دامنه)
ماندگاری دائمی (تا زمانی که کاربر پاک کند) دارای تاریخ انقضا، یا تا پایان جلسه
ارسال به سرور خیر، فقط سمت کلاینت بله، در هر درخواست HTTP به سرور ارسال می شود
امنیت آسیب پذیر در برابر XSS، رمزنگاری دستی نیاز دارد آسیب پذیر در برابر XSS و CSRF، گزینه های امنیتی مانند HttpOnly
سادگی استفاده API ساده و مستقیم (setItem, getItem) پیچیده تر، نیاز به تجزیه رشته ای (پارس کردن)
دسترسی دسترسی آسان با JavaScript دسترسی با JavaScript و سرور

یکی از مهم ترین تفاوت ها این است که کوکی ها در هر درخواست HTTP به سرور ارسال می شوند، حتی اگر سرور به آن ها نیازی نداشته باشد. این موضوع می تواند باعث افزایش حجم درخواست ها و کاهش عملکرد شود. در مقابل، Local Storage داده ها را فقط در سمت کلاینت نگه می دارد و هرگز به سرور ارسال نمی کند، مگر اینکه برنامه نویس به طور صریح این کار را انجام دهد. این مزیت، Local Storage را برای ذخیره داده های پرکاربرد که فقط در سمت کلاینت مورد نیاز هستند، بسیار کارآمدتر می کند.

متدهای اصلی کار با Local Storage (همراه با مثال های کد کامل و قابل اجرا)

کار با Local Storage از طریق یک رابط API بسیار ساده انجام می شود. شیء localStorage متدهای کلیدی را برای مدیریت داده ها ارائه می دهد. در ادامه به بررسی این متدها با مثال های عملی می پردازیم.

localStorage.setItem(key, value): ذخیره داده ها

متد setItem() برای ذخیره یک جفت کلید-مقدار جدید در Local Storage استفاده می شود. این متد دو آرگومان می پذیرد: key (نامی که برای بازیابی داده استفاده می شود) و value (داده ای که می خواهید ذخیره کنید). هر دو آرگومان باید از نوع رشته (String) باشند. اگر key مورد نظر از قبل وجود داشته باشد، value جدید جایگزین مقدار قبلی می شود.

مثال: ذخیره یک رشته ساده (نام کاربری، تنظیم تم)

// ذخیره نام کاربری localStorage.setItem(‘username’, ‘علی’); // ذخیره تنظیمات تم localStorage.setItem(‘theme’, ‘dark’); // بازیابی و نمایش console.log(localStorage.getItem(‘username’)); // خروجی: علی console.log(localStorage.getItem(‘theme’)); // خروجی: dark

نحوه ذخیره آرایه ها و اشیاء (JSON.stringify)

همانطور که اشاره شد، Local Storage فقط می تواند رشته ها را ذخیره کند. این یک محدودیت مهم است، زیرا در توسعه وب مدرن، اغلب با آرایه ها و اشیاء جاوا اسکریپت سروکار داریم. برای ذخیره این نوع داده ها، باید آن ها را قبل از ذخیره سازی به رشته JSON تبدیل کنیم. این کار با استفاده از متد JSON.stringify() انجام می شود.

// یک شیء جاوا اسکریپت const userSettings = { fontSize: ’16px’, darkMode: true, notifications: [’email’, ‘sms’] }; // تبدیل شیء به رشته JSON و ذخیره در Local Storage localStorage.setItem(‘user_preferences’, JSON.stringify(userSettings)); // حالا ‘user_preferences’ یک رشته JSON در Local Storage است console.log(localStorage.getItem(‘user_preferences’)); // خروجی: {fontSize:16px,darkMode:true,notifications:[email,sms]}

localStorage.getItem(key): بازیابی داده ها

متد getItem() برای بازیابی مقدار مرتبط با یک key مشخص از Local Storage استفاده می شود. این متد تنها یک آرگومان (key) را می پذیرد و مقدار ذخیره شده را به صورت یک رشته برمی گرداند. اگر key مورد نظر در Local Storage وجود نداشته باشد، این متد null را برمی گرداند.

مثال: بازیابی رشته

// فرض می کنیم ‘username’ قبلاً ذخیره شده است const storedUsername = localStorage.getItem(‘username’); console.log(storedUsername); // خروجی: علی (اگر ذخیره شده باشد، در غیر این صورت null) const nonExistentKey = localStorage.getItem(‘nonexistent’); console.log(nonExistentKey); // خروجی: null

نحوه بازیابی و تبدیل آرایه ها و اشیاء (JSON.parse)

هنگامی که یک آرایه یا شیء را به صورت رشته JSON در Local Storage ذخیره کرده ایم، برای استفاده مجدد از آن در جاوا اسکریپت، باید آن رشته JSON را دوباره به ساختار داده اصلی (آرایه یا شیء) تبدیل کنیم. این کار با استفاده از متد JSON.parse() انجام می شود.

همچنین، قبل از استفاده از JSON.parse()، همیشه توصیه می شود وجود مقدار را بررسی کنید. زیرا اگر getItem() مقدار null را برگرداند و شما مستقیماً JSON.parse(null) را فراخوانی کنید، ممکن است خطایی رخ دهد یا مقداری ناخواسته (مانند null به جای یک شیء) تولید شود. این بررسی به جلوگیری از خطاهای احتمالی کمک می کند.

// فرض می کنیم ‘user_preferences’ قبلاً به صورت رشته JSON ذخیره شده است const storedPreferencesJSON = localStorage.getItem(‘user_preferences’); let userPreferences = {}; if (storedPreferencesJSON) { userPreferences = JSON.parse(storedPreferencesJSON); } console.log(userPreferences); /خروجی (اگر ذخیره شده باشد): { fontSize: ’16px’, darkMode: true, notifications: [’email’, ‘sms’] } / console.log(userPreferences.darkMode); // خروجی: true

localStorage.removeItem(key): حذف یک مورد خاص

متد removeItem() برای حذف یک جفت کلید-مقدار خاص از Local Storage استفاده می شود. این متد یک آرگومان (key) را می پذیرد. اگر key مورد نظر وجود نداشته باشد، متد هیچ عملیاتی انجام نمی دهد و خطایی نیز رخ نمی دهد.

مثال: حذف یک تنظیم خاص

// ابتدا یک کلید را ذخیره می کنیم localStorage.setItem(‘temp_data’, ‘این یک داده موقت است’); console.log(localStorage.getItem(‘temp_data’)); // خروجی: این یک داده موقت است // سپس آن را حذف می کنیم localStorage.removeItem(‘temp_data’); console.log(localStorage.getItem(‘temp_data’)); // خروجی: null

localStorage.clear(): حذف تمام داده ها

متد clear() برای حذف تمامی جفت های کلید-مقدار ذخیره شده برای یک دامنه (Origin) خاص در Local Storage استفاده می شود. این متد هیچ آرگومانی را نمی پذیرد و به محض فراخوانی، کل فضای ذخیره سازی Local Storage مربوط به آن دامنه را پاک می کند. در استفاده از این متد باید احتیاط کرد، زیرا تمام اطلاعات کاربر مرتبط با آن وب سایت حذف خواهند شد.

مثال: پاک کردن کل داده های مربوط به یک Origin

// ذخیره چند مورد برای تست localStorage.setItem(‘setting1’, ‘value1’); localStorage.setItem(‘setting2’, ‘value2’); console.log(localStorage.length); // خروجی: 2 (یا بیشتر اگر موارد دیگری هم باشند) // پاک کردن همه چیز localStorage.clear(); console.log(localStorage.length); // خروجی: 0 console.log(localStorage.getItem(‘setting1’)); // خروجی: null

localStorage.key(index): دسترسی به نام کلید بر اساس ایندکس

متد key() برای بازیابی نام کلیدی که در یک ایندکس (موقعیت) مشخص در Local Storage قرار دارد، استفاده می شود. این متد یک آرگومان (index) را می پذیرد که باید یک عدد صحیح (Integer) باشد. ایندکس ها از 0 شروع می شوند. اگر index معتبری ارائه شود، نام کلید را برمی گرداند؛ در غیر این صورت، null را بازمی گرداند.

مثال: پیمایش کلیدها (مفید برای اشکال زدایی یا نمایش)

// ذخیره چند مورد localStorage.setItem(‘firstKey’, ‘اولین مقدار’); localStorage.setItem(‘secondKey’, ‘دومین مقدار’); // پیمایش و نمایش تمامی کلیدها for (let i = 0; i < localStorage.length; i++) { const keyName = localStorage.key(i); console.log(`کلید در ایندکس ${i}: ${keyName}`); } /خروجی (ممکن است ترتیب متفاوت باشد): کلید در ایندکس 0: firstKey کلید در ایندکس 1: secondKey / const keyAtIndexZero = localStorage.key(0); console.log(keyAtIndexZero); // خروجی: firstKey (یا کلید دیگری در ایندکس 0) const outOfBoundsKey = localStorage.key(100); console.log(outOfBoundsKey); // خروجی: null

Local Storage یک ابزار قدرتمند برای ذخیره سازی داده های سمت کلاینت است که با ارائه متدهای ساده و کارآمد، به توسعه دهندگان امکان مدیریت اطلاعات پایدار در مرورگر را می دهد و تجربه کاربری را به طور چشمگیری بهبود می بخشد.

موارد استفاده عملی و سناریوهای کاربردی Local Storage

Local Storage به دلیل پایداری و سهولت استفاده، در سناریوهای مختلف توسعه وب کاربردهای فراوانی دارد. شناخت این موارد کمک می کند تا از آن به طور مؤثرتری بهره ببریم:

  • ذخیره تنظیمات کاربر: یکی از رایج ترین کاربردها، ذخیره تنظیمات شخصی سازی شده توسط کاربر است. این شامل انتخاب تم تیره/روشن، زبان رابط کاربری، اندازه فونت، ترجیحات نمایش لیست و غیره می شود. با ذخیره این تنظیمات، کاربر در هر بار بازدید از سایت، تجربه شخصی سازی شده خود را حفظ می کند.
  • حفظ وضعیت فرم ها: تصور کنید کاربر در حال پر کردن یک فرم طولانی است و به طور تصادفی صفحه را رفرش می کند یا مرورگر بسته می شود. با استفاده از Local Storage، می توان داده های واردشده در فرم را به طور خودکار ذخیره کرد و در صورت نیاز، آن ها را بازیابی نمود تا از از دست رفتن اطلاعات جلوگیری شود.
  • کش کردن داده های پرکاربرد: برای بهبود سرعت بارگذاری و کاهش بار روی سرور، می توان داده هایی که کمتر تغییر می کنند (مانند لیست محصولات، مقالات یا اطلاعات پروفایل) را در Local Storage کش کرد. این امر به برنامه ها امکان می دهد تا در حالت آفلاین نیز به بخشی از اطلاعات دسترسی داشته باشند.
  • ذخیره Tokenهای احراز هویت: در بسیاری از برنامه های Single Page Application (SPA)، توکن های احراز هویت (مانند JWT) پس از ورود کاربر، در Local Storage ذخیره می شوند تا در درخواست های بعدی به سرور مورد استفاده قرار گیرند. البته، این روش با ملاحظات امنیتی خاصی همراه است که باید رعایت شود.
  • ایجاد یک سبد خرید ساده در سمت کلاینت: برای وب سایت های فروشگاهی ساده یا پروتوتایپ ها، می توان آیتم های سبد خرید را در Local Storage ذخیره کرد. این کار نیاز به ارتباط مداوم با سرور را کاهش می دهد و تجربه خرید سریع تری را فراهم می کند.

مزایا و معایب استفاده از Local Storage

مانند هر فناوری دیگری، Local Storage نیز دارای مزایا و معایب خاص خود است که آگاهی از آن ها برای استفاده صحیح و بهینه از آن ضروری است.

مزایا

  1. ظرفیت ذخیره سازی بالا: Local Storage ظرفیت ذخیره سازی بسیار بیشتری نسبت به کوکی ها دارد (معمولاً 5 تا 10 مگابایت در مقایسه با 4 کیلوبایت کوکی ها). این امکان ذخیره حجم قابل توجهی از داده ها را فراهم می کند.
  2. ماندگاری داده ها در طولانی مدت (Persistence): داده ها در Local Storage تاریخ انقضا ندارند و تا زمانی که کاربر آن ها را دستی پاک نکند یا برنامه آن ها را حذف نکند، باقی می مانند. این برای حفظ تنظیمات و وضعیت کاربر در طولانی مدت بسیار مفید است.
  3. عدم نیاز به درخواست سرور: داده های Local Storage فقط در سمت کلاینت نگهداری می شوند و به طور خودکار در هر درخواست HTTP به سرور ارسال نمی شوند. این امر باعث کاهش حجم ترافیک شبکه، بهبود سرعت بارگذاری صفحه و کاهش بار روی سرور می شود.
  4. سادگی استفاده و API قابل فهم: API Local Storage بسیار ساده و مستقیم است و شامل متدهای معدودی مانند setItem()، getItem()، removeItem() و clear() است که کار با آن را آسان می کند.
  5. دسترسی آفلاین به داده های کش شده: با ذخیره داده های مهم در Local Storage، وب سایت ها می توانند تا حدی در حالت آفلاین نیز به این اطلاعات دسترسی داشته باشند و تجربه کاربری بهتری را ارائه دهند.

معایب

  1. ذخیره سازی فقط رشته ها: Local Storage فقط می تواند داده ها را به صورت رشته ذخیره کند. برای ذخیره انواع داده های پیچیده تر مانند آرایه ها یا اشیاء جاوا اسکریپت، نیاز به تبدیل آن ها به رشته JSON (با JSON.stringify()) و سپس بازگرداندن آن ها (با JSON.parse()) است که پیچیدگی کد را افزایش می دهد.
  2. عملیات هم زمان (Synchronous): تمامی عملیات Local Storage به صورت هم زمان (Synchronous) انجام می شوند. این بدان معناست که در حین خواندن یا نوشتن داده های حجیم، Main Thread مرورگر ممکن است برای مدت کوتاهی بلاک شود و باعث کندی یا عدم پاسخگویی رابط کاربری (UI) شود.
  3. عدم امنیت برای داده های حساس: داده های ذخیره شده در Local Storage توسط هر کد جاوا اسکریپتی که در همان Origin (دامنه) اجرا می شود، قابل دسترسی هستند. این بدان معناست که اگر وب سایت شما دچار حملات XSS (Cross-Site Scripting) شود، مهاجم می تواند به راحتی به تمام داده های Local Storage دسترسی پیدا کند. بنابراین، هرگز نباید اطلاعات کاملاً حساس مانند رمز عبور یا اطلاعات بانکی را در Local Storage ذخیره کرد.
  4. عدم وجود مکانیزم داخلی برای مدیریت انقضا: Local Storage به طور پیش فرض مکانیزمی برای تنظیم تاریخ انقضا یا Garbage Collection (پاک سازی خودکار داده های قدیمی) ندارد. مدیریت این موارد بر عهده توسعه دهنده است.
  5. حجم بالای داده می تواند منجر به افت عملکرد شود: اگرچه ظرفیت بالایی دارد، ذخیره حجم بسیار زیاد داده در Local Storage می تواند بر عملکرد کلی برنامه، به ویژه در زمان های بارگذاری اولیه یا هنگام عملیات هم زمان، تأثیر منفی بگذارد.

مشاهده و مدیریت Local Storage در ابزارهای توسعه دهنده مرورگر (DevTools)

ابزارهای توسعه دهنده (DevTools) مرورگرها، محیطی قدرتمند برای بازرسی، اشکال زدایی و مدیریت داده های ذخیره شده در مرورگر فراهم می کنند. مشاهده و مدیریت Local Storage در این ابزارها بسیار ساده است:

  1. باز کردن DevTools: در اکثر مرورگرها (مانند Chrome، Firefox، Edge)، می توانید با کلیک راست روی هر جای صفحه و انتخاب Inspect یا Inspect Element (یا با فشردن کلید F12) ابزارهای توسعه دهنده را باز کنید.
  2. پیمایش به تب Application/Storage: پس از باز شدن DevTools، به دنبال تبی با عنوان Application یا Storage (در فایرفاکس) باشید و روی آن کلیک کنید.
  3. انتخاب Local Storage: در نوار کناری سمت چپ تب Application یا Storage، بخشی به نام Storage یا Local Storage را پیدا خواهید کرد. روی Local Storage کلیک کنید تا زیرمجموعه دامنه های مختلف را ببینید.
  4. باز کردن و مشاهده محتویات: روی دامنه ای که می خواهید Local Storage آن را مشاهده کنید (معمولاً دامنه ای که در حال حاضر در آن هستید) کلیک کنید. با این کار، جدولی از تمامی جفت های کلید-مقدار ذخیره شده در Local Storage برای آن دامنه نمایش داده می شود. شما می توانید کلیدها و مقادیر را مشاهده، ویرایش یا حذف کنید.

این قابلیت به توسعه دهندگان کمک می کند تا به راحتی داده های ذخیره شده را اشکال زدایی کنند، تغییرات را تست کنند و از صحت عملکرد مکانیزم ذخیره سازی اطمینان حاصل نمایند.

پشتیبانی مرورگرها و بررسی وجود Local Storage

Local Storage به عنوان بخشی از استاندارد HTML5، از پشتیبانی گسترده ای در مرورگرهای مدرن برخوردار است. تقریباً تمامی مرورگرهای اصلی مانند Google Chrome، Mozilla Firefox، Microsoft Edge، Safari و Opera از آن پشتیبانی می کنند. حتی نسخه های قدیمی تر Internet Explorer (از IE8 به بعد) نیز این قابلیت را ارائه می دهند. بنابراین، در اکثر موارد، نیازی به نگرانی بابت سازگاری نخواهید داشت.

با این حال، برای اطمینان بیشتر، به ویژه در محیط هایی که ممکن است مرورگرهای بسیار قدیمی یا خاص استفاده شوند، می توانید به صورت برنامه نویسی (Programmatically) وجود Local Storage را بررسی کنید. این کار به شما امکان می دهد تا یک راهکار جایگزین (Fallback) ارائه دهید یا از اجرای کدی که به Local Storage وابسته است، جلوگیری کنید.

function storageAvailable(type) { let storage; try { storage = window[type]; const x = ‘__storage_test__’; storage.setItem(x, x); storage.removeItem(x); 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 // everything except Firefox e.name === ‘QuotaExceededError’ || // Firefox e.name === ‘NS_ERROR_DOM_QUOTA_REACHED’) && // acknowledge QuotaExceededError only if there’s something already stored storage && storage.length !== 0 ); } } if (storageAvailable(‘localStorage’)) { // Local Storage پشتیبانی می شود، می توانید از آن استفاده کنید console.log(‘Local Storage در دسترس است.’); } else { // Local Storage پشتیبانی نمی شود، از راهکار جایگزین استفاده کنید console.log(‘Local Storage در دسترس نیست.’); }

این تابع با تلاش برای نوشتن و سپس حذف یک آیتم آزمایشی در Local Storage، وجود و قابلیت استفاده از آن را بررسی می کند. این یک الگوی رایج برای اطمینان از سازگاری است.

یک پروژه عملی: ساخت یک To-Do List ساده با Local Storage

برای درک عمیق تر و کاربردی تر Local Storage در جاوا اسکریپت، یک پروژه ساده To-Do List (لیست وظایف) را پیاده سازی می کنیم که قابلیت های افزودن، حذف و حفظ وظایف را حتی پس از بسته شدن مرورگر، با استفاده از Local Storage فراهم می کند.

ساختار HTML: ایجاد عناصر ورودی و نمایش لیست

ابتدا، فایل index.html را با ساختار پایه ای که شامل یک فیلد ورودی برای افزودن وظایف جدید و یک لیست نامرتب (ul) برای نمایش وظایف است، آماده می کنیم.

لیست وظایف من

افزودن وظیفه

پاک کردن همه

استایل دهی CSS: (ساده و مینیمال)

برای ظاهر بهتر، یک فایل style.css با استایل های ساده ایجاد می کنیم.

body { font-family: Arial, sans-serif; background-color: #f4f4f4; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; } .container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); width: 400px; max-width: 90%; } h1 { text-align: center; color: #333; } #taskInput { width: calc(100% – 100px); padding: 10px; margin-right: 10px; border: 1px solid #ddd; border-radius: 4px; } #addTaskBtn { padding: 10px 15px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; } #addTaskBtn:hover { background-color: #218838; } #taskList { list-style: none; padding: 0; margin-top: 20px; } #taskList li { background-color: #e9ecef; padding: 10px; margin-bottom: 8px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; } #taskList li button { background-color: #dc3545; color: white; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; } #taskList li button:hover { background-color: #c82333; } #clearAllBtn { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; margin-top: 15px; } #clearAllBtn:hover { background-color: #0056b3; }

منطق JavaScript:

در فایل script.js، منطق اصلی برنامه را پیاده سازی می کنیم. این شامل بارگذاری وظایف ذخیره شده، افزودن وظیفه جدید و حذف وظایف است.

const taskInput = document.getElementById(‘taskInput’); const addTaskBtn = document.getElementById(‘addTaskBtn’); const taskList = document.getElementById(‘taskList’); const clearAllBtn = document.getElementById(‘clearAllBtn’); let tasks = []; // تابع برای بارگذاری وظایف از Local Storage function loadTasks() { const storedTasks = localStorage.getItem(‘tasks’); if (storedTasks) { tasks = JSON.parse(storedTasks); renderTasks(); } } // تابع برای ذخیره وظایف در Local Storage function saveTasks() { localStorage.setItem(‘tasks’, JSON.stringify(tasks)); } // تابع برای نمایش وظایف در UI function renderTasks() { taskList.innerHTML = ”; // پاک کردن لیست فعلی tasks.forEach((task, index) => { const li = document.createElement(‘li’); li.textContent = task; const deleteButton = document.createElement(‘button’); deleteButton.textContent = ‘حذف’; deleteButton.onclick = () => deleteTask(index); li.appendChild(deleteButton); taskList.appendChild(li); }); } // تابع برای افزودن وظیفه جدید addTaskBtn.addEventListener(‘click’, () => { const newTask = taskInput.value.trim(); if (newTask !== ”) { tasks.push(newTask); taskInput.value = ”; // پاک کردن ورودی saveTasks(); renderTasks(); } }); // تابع برای حذف یک وظیفه function deleteTask(index) { tasks.splice(index, 1); // حذف از آرایه saveTasks(); renderTasks(); } // تابع برای پاک کردن همه وظایف clearAllBtn.addEventListener(‘click’, () => { if (confirm(‘آیا مطمئن هستید که می خواهید همه وظایف را پاک کنید؟’)) { tasks = []; saveTasks(); renderTasks(); } }); // بارگذاری وظایف هنگام بارگذاری اولیه صفحه document.addEventListener(‘DOMContentLoaded’, loadTasks);

تشریح گام به گام پیاده سازی:

  1. تعریف متغیرها: ابتدا عناصر HTML را با استفاده از document.getElementById() به متغیرهای جاوا اسکریپت متصل می کنیم. یک آرایه tasks برای نگهداری وظایف ایجاد می شود.
  2. loadTasks(): این تابع در ابتدای بارگذاری صفحه اجرا می شود. وظایف ذخیره شده در Local Storage (با کلید ‘tasks’) را بازیابی می کند. اگر داده ای وجود داشته باشد، آن را با JSON.parse() به آرایه تبدیل کرده و در متغیر tasks قرار می دهد، سپس renderTasks() را فراخوانی می کند.
  3. saveTasks(): این تابع وظیفه ذخیره آرایه tasks را در Local Storage بر عهده دارد. قبل از ذخیره، آرایه را با JSON.stringify() به رشته JSON تبدیل می کند.
  4. renderTasks(): مسئول به روزرسانی رابط کاربری است. ابتدا محتوای لیست ul را پاک کرده، سپس بر اساس آرایه tasks، برای هر وظیفه یک li جدید ایجاد می کند، دکمه حذف را به آن اضافه کرده و به ul اصلی می افزاید.
  5. افزودن وظیفه جدید: با کلیک روی دکمه افزودن وظیفه، مقدار taskInput گرفته می شود. اگر خالی نباشد، به آرایه tasks اضافه شده، فیلد ورودی پاک می شود، سپس saveTasks() و renderTasks() فراخوانی می شوند.
  6. حذف وظیفه: هر دکمه حذف در کنار یک وظیفه، با فراخوانی deleteTask(index)، وظیفه مربوطه را از آرایه tasks حذف کرده، سپس saveTasks() و renderTasks() را برای به روزرسانی اجرا می کند.
  7. پاک کردن همه وظایف: دکمه پاک کردن همه با تأیید کاربر، آرایه tasks را خالی کرده، سپس saveTasks() و renderTasks() را فراخوانی می کند.
  8. بارگذاری اولیه: رویداد DOMContentLoaded تضمین می کند که loadTasks() تنها پس از بارگذاری کامل ساختار HTML اجرا شود.

این پروژه نشان می دهد که چگونه می توان با چند خط کد ساده و استفاده از Local Storage، یک برنامه کاربردی با قابلیت حفظ داده ها در مرورگر ایجاد کرد.

نکات امنیتی و بهترین شیوه ها در استفاده از Local Storage

اگرچه Local Storage ابزاری قدرتمند است، اما باید با احتیاط و آگاهی از مسائل امنیتی آن استفاده شود. رعایت بهترین شیوه ها برای محافظت از داده های کاربر ضروری است:

  1. عدم ذخیره اطلاعات کاملاً حساس: هرگز اطلاعاتی مانند رمز عبور، اطلاعات بانکی، شماره کارت اعتباری یا سایر اطلاعات شخصی بسیار حساس را در Local Storage ذخیره نکنید. این داده ها می توانند توسط حملات XSS (Cross-Site Scripting) به راحتی به سرقت بروند. برای داده های حساس، از راه حل های امن تر سمت سرور یا مکانیزم های رمزنگاری پیشرفته استفاده کنید.
  2. اعتبار سنجی و پاک سازی داده های ورودی: قبل از ذخیره هر گونه داده ای در Local Storage، اطمینان حاصل کنید که آن داده ها معتبر هستند و حاوی کدهای مخرب نیستند. همچنین، پس از بازیابی داده ها، آن ها را مجدداً اعتبار سنجی و پاک سازی کنید تا از تزریق کد (Code Injection) به رابط کاربری جلوگیری شود.
  3. محدود کردن حجم داده های ذخیره شده: با وجود ظرفیت بالا، از ذخیره حجم بسیار زیاد داده در Local Storage خودداری کنید. این می تواند منجر به کاهش عملکرد مرورگر، به ویژه در زمان عملیات هم زمان، شود. داده ها را به حداقل مقدار لازم محدود کنید.
  4. توجه به حملات XSS (Cross-Site Scripting): این مهم ترین نگرانی امنیتی Local Storage است. یک کد جاوا اسکریپت مخرب که از طریق XSS در صفحه شما تزریق می شود، می تواند به راحتی به localStorage دسترسی پیدا کرده و تمام داده های آن را بخواند، تغییر دهد یا حذف کند. بنابراین، اولویت اصلی در توسعه وب، جلوگیری از حملات XSS است.
  5. استفاده از رمزنگاری برای داده های نیمه حساس: اگر نیاز به ذخیره داده هایی دارید که کمی حساس هستند اما نه به اندازه رمز عبور (مثلاً تنظیمات کاربری که شامل اطلاعات نیمه خصوصی است)، می توانید قبل از ذخیره آن ها در Local Storage، آن ها را رمزنگاری (Encrypt) کنید. البته این کار پیچیدگی کد را افزایش می دهد و باید با دقت انجام شود، زیرا کلید رمزنگاری نیز باید در جایی امن نگهداری شود.

رعایت این نکات به شما کمک می کند تا از مزایای Local Storage بهره مند شوید و در عین حال، امنیت و پایداری برنامه خود را حفظ کنید. اگر به دنبال آموزش جامع و عمیق تر در زمینه آموزش جاوا اسکریپت و مباحث پیشرفته تر توسعه وب هستید، مجتمع فنی تهران دوره های تخصصی از آموزش مقدماتی تا پیشرفته جاوا اسکریپت را ارائه می دهد. این دوره ها شامل مباحثی چون آموزش JavaScript پروژه محور هستند که برای تبدیل شما به یک توسعه دهنده حرفه ای طراحی شده اند. با ثبت نام در دوره آموزش جاوا اسکریپت در مجتمع فنی تهران، می توانید مهارت های خود را در این زمینه تقویت کرده و با جدیدترین تکنیک ها و بهترین شیوه های توسعه وب آشنا شوید.

آموزش کار با Local Storage در جاوا اسکریپت

سوالات متداول

آیا Local Storage می تواند جایگزین کامل پایگاه داده سمت سرور برای یک وب سایت پیچیده شود؟

خیر، Local Storage برای ذخیره حجم کم تا متوسط داده های سمت کلاینت طراحی شده و هرگز جایگزین کامل پایگاه داده سمت سرور برای مدیریت داده های پیچیده، احراز هویت قوی، یا همگام سازی بین چندین کاربر نمی شود.

چگونه می توان اطلاعات حساس (مانند توکن های احراز هویت) را به صورت نسبتاً امن در Local Storage ذخیره کرد، با در نظر گرفتن محدودیت های امنیتی آن؟

برای توکن های احراز هویت، معمولاً توصیه می شود به جای Local Storage از HttpOnly Cookies استفاده شود، زیرا از حملات XSS محافظت می کنند؛ اما اگر چاره ای جز Local Storage نیست، توکن ها باید رمزنگاری شده و دارای طول عمر کوتاه باشند تا ریسک امنیتی کاهش یابد.

تفاوت اصلی localStorage و cookies از نظر امنیت و آسیب پذیری در برابر حملات XSS چیست؟

Local Storage و Cookies هر دو در برابر XSS آسیب پذیرند. اما Cookies با تنظیمات HttpOnly می توانند از دسترسی جاوا اسکریپت به آن ها جلوگیری کنند، قابلیتی که Local Storage فاقد آن است و این Cookies را برای توکن های حساس امن تر می کند.

آیا استفاده بیش از حد از localStorage برای ذخیره داده های بسیار بزرگ یا عملیات مکرر بر عملکرد وب سایت و پاسخگویی مرورگر تاثیر منفی می گذارد؟

بله، Local Storage عملیات هم زمان دارد. ذخیره داده های بسیار بزرگ یا انجام عملیات مکرر روی آن می تواند باعث بلاک شدن Main Thread مرورگر و افت عملکرد و پاسخگویی رابط کاربری شود.

چه زمانی باید به جای localStorage از IndexedDB یا دیگر راه حل های ذخیره سازی پیشرفته تر در جاوا اسکریپت استفاده کنیم؟

اگر نیاز به ذخیره حجم زیادی از داده های ساختاریافته (مانند پایگاه داده رابطه ای)، انجام جستجوهای پیچیده، یا عملیات ناهم زمان (Asynchronous) دارید، IndexedDB یا سایر APIهای مشابه مانند Web SQL (که منسوخ شده) یا Libraries مانند LocalForage گزینه های مناسب تری هستند.

دکمه بازگشت به بالا