Javascript local storage is One of those hidden gems of the browser that really helps bring the modern web application to life in terms of being able to personalize and offer a smoother overall experience. If you’ve ever returned to a website that had saved your preferences (like switching between light/dark modes), or if you’ve opened a shopping cart weeks later and seen that all the items were still waiting for you, you’ve already experienced the power of javascript local storage! Javascript local storage is simply a small key-value-based storage system embedded directly in the browser that enables you to save data locally for an individual user’s browser session, both across page reloads and across entirely independent browsing sessions.
Think of local storage similar to a small notebook that resides within a user’s browser. With each subsequent visit to your site, you can enter into that notebook a note or two (or dozens!) such as “this user likes dark mode,” or “the last item viewed was sneakers.” And upon returning to your site next week or month, you pull out the notebook again and continue where you left off. However, unlike a physical notebook that could potentially become lost or damaged and thus losing your previously entered information forever, the digital version of that notebook remains within the browser until either you delete it programmatically or the user cleans out their browser history/data.
As wonderful as javascript local storage is, there are indeed nuances involved with implementing it effectively. In order to move past merely copying/pasting snippets for javascript local storage into having confidence in your ability to implement it successfully; let’s go step by step through five core concepts.
Core concepts behind Understanding how to effectively use javascript local storage
The javascript local storage api is quite minimalist with only One global Object available for working with local storage. That global Object is called “localstorage”, and it contains a very limited amount of methods and for most of your time using local storage, you will likely end up using only 4 of them.
Setitem() is the workhorse method provided by the “localstorage” api. As shown below, this method takes two parameters a key and a value. Once a key value pair is passed to “setitem()”, it is saved in the browser’s local storage area for the current “origin.” an origin consists of three components: protocol (http or https), domain (example.com), and port (80 by default.) therefore, http://example.com would have an origin that differs from https://example.com. Additionally, each origin has its own unique bucket for saving data in local storage. So if a user visits example.com and saves something in local storage; visiting https://example.com would result in an entirely separate bucket for that origin.
When calling “setitem()”, if you attempt to overwrite an existing key; “setitem()” will silently replace whatever existed under that key previously. Conversely; if the given key does not already exist in local storage; “setitem()” will create a brand-new entry.
To obtain the data from local storage you call “getitem()”. When passing the exact same key used during the initial “setitem()” call; “getitem()” returns the corresponding value as a string. If however; the specified key does not exist in local storage; “getitem()” returns “null.”
This is an important point regarding checking for “null”. This is the only reliable means of determining whether a specific key has been created/set previously in local storage.
There are two additional methods available for cleaning up once you’re done with data saved in local storage. One method, “removeitem()”, removes a single key value pair from local storage. The second method,”clear()”, removes all entries from local storage for the current origin.
Finally; as an added bonus; “localstorage” provides a “length” property that indicates the total count of keys currently stored within local storage. While this may seem trivial at first glance; it can be very helpful when troubleshooting issues related to local storage or developing an interface for managing local storage.
An additional consideration when using local storage is that you can technically reference values using dot notation similar to how you would refer to properties of an Object (i.e., “localstorage.mykey”). While this approach does function as expected; it is highly recommended that you adhere strictly to utilizing “setitem()” and “getitem()” for referencing values in local storage due to potential pitfalls related to using plain objects as a basis for a key value store.
Storing objects & arrays using javascript local storage
One common pitfall awaiting nearly every developer who uses javascript local storage for the first-time revolves around attempting to store a javascript Object directly in local storage. Unfortunately; when you try to do so regardless of the actual contents of the Object, the result will be disappointing.
The issue lies in that local storage only supports strings as acceptable values. Since keys and values alike are inherently strings; any non-string values passed to “setitem()” will be automatically converted to a string representation. As stated before; when converting an Object (regardless of type) to a string, the resulting string will typically be [Object Object].
Therefore; in order to store objects and arrays using javascript local storage, we need to manually convert them into json strings prior to storing them using “json.stringify()”. Likewise; we need to parse the retrieved json strings back into usable javascript representations prior to attempting to utilize them using “json.parse()”.
Using this paradigm yields results as follows:
Var user = {name: 'Alex', preferences: {theme: 'dark', fontsize: 16}};
Localstorage.setitem(‘user’, JSON.stringify(user)); // store user Object Later…
Var storeduser = json.parse(localstorage.getitem(“user")); // parse user Object
Console.log(storeduser.preferences.theme); // output: ‘dark’ At first glance; this appears as though it involves some additional overhead compared to other methods of storing data but once practiced repeatedly; this process quickly becomes second nature and eliminates countless hours spent staring blankly at the console asking oneself “where did my perfectly good Object go?!?” for further explanation and edge case examples involving this pattern, please consult the freecodecamp guide on storing objects in local storage.
Local storage vs session storage vs cookies
Knowing when to utilize javascript local storage versus its cousins is equally as important as Understanding how to properly utilize it. The web storage api itself offers two mechanisms: localstorage and sessionstorage. Both mechanisms exhibit virtually identical behavior; utilizing equivalent syntax and offering equivalent limitations regarding only accepting strings. The primary distinction lies exclusively in regards to duration.
Data stored within sessionstorage survives page reloads but is deleted upon closure of the browser tab/window. Each tab enjoys its own private session storage area.
On the other hand; data stored within localstorage continues indefinitely; remaining stored regardless of closures/reboots/upgrades/etc…of the os/browser/etc…it remains there until javascript intentionally deletes it or the user manually deletes their browser history/data.
Due to this persistence; javascript local storage proves invaluable for retaining user preferences and caching application state.
Next; there are cookies. Cookies represent the older/traditional mechanism for storing client side data. Due to cookies being automatically transmitted with every http request; they are ideal for use with authentication tokens that require validation by the server. Data stored within cookies never communicates with servers unless intentionally sent via javascript. Cookies also have a severe limitation regarding size approximately 4kb per domain whereas local storage typically exceeds 5mb.
Your general guideline should be: utilize local storage for non sensitive client-side preferences/cached data. Utilize sessionstorage for transient/tab specific state. Utilize cookies solely when the server requires read-access to said data on every request.
Security limitations of javascript local storage
While javascript local storage grants plenty of room for data storage, it is far from unlimited. Most browsers assign roughly 5mb of space per origin although some browsers may grant up to 10mb depending on various factors including browser/platform/etc…
However, as mentioned above this is ample room compared to cookies’ paltry 4kb size limit per domain but it is still far from sufficient space to use as a database. Large binary files and/or complete application state dumps should therefore be relegated to IndexedDB which possesses exponentially greater capacity than local storage.
Far greater concerns surrounding local storage lie in regards to security. Because any javascript code executing on your origin can access all data residing within local storage, this encompasses third party scripts from analytics providers/advertising networks/npm modules installed six months ago and long since forgotten but still executing on your-origin plus any other malicious script capable of gaining an XSS exploit against your domain.
For this reason alone; do not store sensitive data in local storage! Passwords/authentication tokens/personally identifiable info/should never be stored in local storage!
According to a recent OWASP report published in 2023, XSS vulnerabilities represented among the top web vulnerabilities with over fifty-percent-of-tested-applications exhibiting exploitable flaws.
Therefore; if you plan on storing tokens/session ids/etc.; use HttpOnly cookies instead which mark cookies as inaccessible by javascript altogether thereby eliminating any chance of data being exfiltrated via XSS attacks!
Local storage should only be treated as public data within your origin
As noted above; since cookies are not accessible via javascript; they cannot be accessed via XSS attacks either! Local storage should therefore only be treated as public data within your origin! It is perfectly fine to store theme preferences/form draft content/etc…in local storage but it should never be used as a secure/vaulted repository.
Detecting storage events across tabs
Perhaps One of the more advanced features included within javascript local storage is detection of storage events. A storage event is fired across all other tabs/windows from the same origin anytime either local storage or session storage is modified by another processing context of that origin. The tab/window performing the modification will not receive this event, every other open tab will.
Storage events enable numerous opportunities for inter-tab communication. For instance; imagine a user has your app open in two different tabs. They change their display name in One tab, you can listen for the storage event within the second tab and update your UI immediately thereby providing seamless synchronization without need for server roundtrip/web socket communication etc….
Upon receipt of a storage event, your event handler receives an Object containing multiple useful attributes including:
• which key was modified
• the old value associated w/the modified key
• the new value associated w/the modified key
• url of document performing modification
These attributes permit you to react/respond only to specific changes rather than re-running entire application state upon detecting any storage event whatsoever.
Note: although storage events can be triggered by modifying local storage via direct assignment (e.g., localstorage.mykey = ‘value’) they will not fire if you modify local storage using Object property syntax (e.g., localstorage.mykey = ‘value’).
Therefore; once again it is highly recommended that you remain consistent in usage patterns and utilize only the api provided methods (setitem(), getitem(), removeitem(), clear()) when working with local storage.
Conclusion
Local storage in JavaScript may appear to be a simple tool but performs far beyond expectations with just four fundamental functions: you are able to save user preference information, store data for caching purposes, and also allow users to share their current state among several open tabs within a single browser application. This document has provided an overview of the four main API functions as well as the common JSON serialization method used to store complex data structures, the key differences in the lifecycles of local and session storage, the security limitations that should always be avoided and the event handler that allows cross-tab communication. Once you understand how to master local storage in JavaScript (when to utilize it, how to properly format the data you wish to store, and at what point you reach the limits of what can be stored), you will have mastered a very useful piece of functionality in web development. If you want to explore further the Web Storage API then refer to the MDN Documentation about Using the Web Storage API for additional details. In addition, if you would like to complete some interactive examples/exercises then refer to the JavaScript.Info Local Storage Guide.
New to HTML? Start Here: HTML Tutorial for Beginners: Your Complete Introduction to HTML Basics
New to CSS? Start Here: CSS Introduction: Master 5 Core Concepts Easily
New to JavaScript? JavaScript Introduction: 5 Proven Steps to Learn JS
[INSERT_ELEMENTOR id=”122″]

