Cookies are small pieces of data stored on the user's device by the web browser. They serve the purpose of persistently storing information that can be retrieved and utilized across different sessions or page visits. The data is typically in the form of key-value pairs, and cookies play a crucial role in maintaining stateful information on the client side.
Cookies are text files that contain small amounts of information. They are stored on the user's device, commonly as text strings. This data is managed by the web browser and sent back and forth between the client and server with each HTTP request, enabling the retention of user-specific information.
One of the primary purposes of cookies is to persistently store information, ensuring that data remains available even when the user navigates away from a webpage and returns later. This is achieved by setting an expiration date for the cookie.
// Set a cookie with the key "username" and value "John Doe"
document.cookie = "username=John Doe";
// Retrieve all cookies
const allCookies = document.cookie;
// Parse individual cookies into an object
const cookies = Object.fromEntries(
allCookies.split("; ").map(cookie => cookie.split("="))
);
// Access a specific cookie value
const username = cookies.username;
Cookies have size limitations (commonly a few kilobytes). Avoid storing large amounts of data in cookies to ensure compatibility and optimal performance.
Session cookies are temporary and expire when the browser is closed, while persistent cookies have a specified expiration date. Choose the appropriate type based on the data's lifecycle.
In summary, cookies are essential for persistently storing small amounts of information on the client side. They enable web applications to remember user preferences, maintain authentication states, and provide a personalized browsing experience. Understanding their definition, purpose, and best practices is fundamental for anyone learning JavaScript and web development.
The document.cookie property is the primary interface for creating and managing cookies in JavaScript. It allows you to set, read, and modify cookies associated with the current document.
The document.cookie property is a string that contains a semicolon-separated list of key-value pairs representing individual cookies. Each key-value pair is separated by an equals sign (=).
// Set a cookie with the key "username" and value "John Doe"
document.cookie = "username=John Doe";
You can add multiple key-value pairs to the document.cookie property by separating them with semicolons.
// Set multiple cookies
document.cookie = "username=John Doe; expires=Thu, 01 Jan 2025 00:00:00 UTC; path=/";
document.cookie = "language=English; max-age=3600; secure";
Cookies can have an optional expiration date, determining how long they persist on the user's device.
Session Cookies: These cookies are temporary and expire when the browser is closed. They don't have an explicit expiration date.
// Set a session cookie
document.cookie = "sessionCookie=value";
Persistent Cookies: These cookies have a specified expiration date, allowing them to persist beyond the current session.
// Set a persistent cookie (expires on January 1, 2025)
document.cookie = "persistentCookie=value; expires=Thu, 01 Jan 2025 00:00:00 UTC";
// Set a persistent cookie with the key "user_id" and value "123"
const expirationDate = new Date();
expirationDate.setFullYear(expirationDate.getFullYear() + 1); // Expires in one year
document.cookie = "user_id=123; expires=" + expirationDate.toUTCString();
// Set a session cookie with the key "visited" and value "true"
document.cookie = "visited=true";
When setting an expiration date for cookies, it's a best practice to use Coordinated Universal Time (UTC) to ensure consistency across different time zones.
Specify the path for the cookie to ensure it's accessible only on specific pages. If not specified, the cookie will be associated with the current page's path by default.
Understanding how to create cookies using document.cookie and setting appropriate expiration dates is crucial for managing user data effectively in web applications. Always consider the lifespan of the information you are storing and follow best practices to enhance the security and efficiency of your cookie management.
To read cookies, you can access the document.cookie property, which contains a semicolon-separated string of all the cookies associated with the current document.
const allCookies = document.cookie;
This code retrieves all cookies as a single string. The string contains key-value pairs separated by semicolons.
To work with individual cookies, you can parse the string into an object.
const cookies = Object.fromEntries(
allCookies.split("; ").map(cookie => cookie.split("="))
);
Here, the split method is used to separate each key-value pair. The resulting array is then transformed into an object using Object.fromEntries.
// Get all cookies
const allCookies = document.cookie;
console.log(allCookies);
// Parse individual cookies into an object
const cookies = Object.fromEntries(
document.cookie.split("; ").map(cookie => cookie.split("="))
);
console.log(cookies);
Before parsing cookies, ensure that there are cookies to parse. If document.cookie is empty, attempting to split it will result in unexpected behavior.
const allCookies = document.cookie.trim();
if (allCookies !== "") {
const cookies = Object.fromEntries(
allCookies.split("; ").map(cookie => cookie.split("="))
);
console.log(cookies);
} else {
console.log("No cookies found.");
}
Cookie values are URL-encoded. When retrieving values, it's essential to decode them using decodeURIComponent to handle special characters.
const username = cookies.username ? decodeURIComponent(cookies.username) : null;
console.log(username);
Reading cookies is a fundamental part of working with client-side data. By understanding how to access and parse cookies using document.cookie, developers can retrieve and utilize stored information. Be mindful of empty cookies, decode values when necessary, and use this knowledge to build dynamic and personalized web experiences.
Once a cookie is set, you can update its value by reassigning a new value to the document.cookie property.
// Update the value of the "username" cookie
document.cookie = "username=New Value";
This will effectively overwrite the existing value of the "username" cookie.
You can modify the expiration date of a cookie to control how long it persists on the user's device.
// Change the expiration date of the "sessionCookie" to 1 hour from now
const expirationDate = new Date();
expirationDate.setTime(expirationDate.getTime() + 60 * 60 * 1000); // 1 hour in milliseconds
document.cookie = "sessionCookie=value; expires=" + expirationDate.toUTCString();
To delete a cookie, you can set its expiration date to a time in the past. This instructs the browser to remove the cookie.
// Delete the "username" cookie
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
By setting the expiration date to a time in the past (commonly the epoch), the browser interprets the cookie as expired and removes it.
// Assume we have an existing "counter" cookie
const currentCounter = parseInt(cookies.counter) || 0;
// Increment the counter and update the cookie
document.cookie = "counter=" + (currentCounter + 1);
// Extend the expiration date of the "sessionToken" cookie to 1 day from now
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 1); // 1 day in the future
document.cookie = "sessionToken=value; expires=" + expirationDate.toUTCString();
// Delete the "language" cookie
document.cookie = "language=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
When modifying or deleting cookies, be explicit about the path and domain to ensure consistency and avoid unexpected behavior.
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=example.com;";
When modifying or updating cookies containing sensitive information, use secure connections (HTTPS) to protect data during transmission.
document.cookie = "secureCookie=value; secure;"; // This cookie will only be sent over HTTPS connections
Understanding how to update, modify, and delete cookies is essential for maintaining accurate and secure client-side data. Practicing caution, being explicit about paths and domains, and utilizing secure practices ensure the effective management of cookies in a web application.
When working with JavaScript, we often need a way to save data directly in the browser so that it can be used later without needing to reload it from a server. Browser storage allows us to do just that, providing a place to store small amounts of data locally on a user’s device.
Why Use Browser Storage?
Imagine you’re creating a website with a color theme that users can personalize. If users select a color, we can store that preference using browser storage so it’s saved even if they leave the page. This is useful for data that should persist across visits, like user settings or saved items in a shopping cart.
Types of Browser Storage:
In this part, we’ll focus on local storage and learn how to store data using JavaScript. By the end of this section, you’ll know how to save, retrieve, and clear data from local storage, as well as why and when it’s useful to do so.
The local storage API in JavaScript gives us a simple and effective way to store data on a user’s browser that persists across sessions. This means users can close the browser, come back, and still access their saved data.
Local storage uses a key-value pair system where each piece of data is associated with a unique key. Data is stored as strings, so when saving complex data structures like objects or arrays, we’ll need to convert them into a string format. Let’s walk through the core methods and explore how each one works.
This method saves data to local storage. It requires two parameters:
localStorage.setItem('username', 'Alice');
In this example, we are saving the string "Alice" with the key "username". Now, as long as the user doesn’t clear their local storage, this value will remain available even after they close and reopen the browser.
• Since local storage only accepts string values, if you want to store a number, object, or array, you must convert it to a string using JSON.stringify(). We’ll cover this in a later section.
The getItem method retrieves data from local storage. It takes a single parameter:
• key: The unique identifier for the data you want to retrieve.
If the specified key exists, this method returns the stored value as a string. If the key does not exist, it returns null.
let username = localStorage.getItem('username');
console.log(username); // Output: “Alice”
Here, we’re retrieving the value associated with "username". If this key doesn’t exist, getItem would return null, which is a useful way to check if a key exists in local storage.
The removeItem method deletes a specific item from local storage. It requires:
• key: The unique identifier of the item to be removed.
localStorage.removeItem('username');
After executing this code, the "username" key and its associated data will be removed from local storage. Attempting to retrieve it afterward with getItem will return null.
This method removes all data from local storage. Unlike removeItem, it doesn’t require any parameters and will delete everything saved in local storage.
localStorage.clear();
Use clear() with caution, as it erases all data, not just specific items. This can be useful if you want to reset all saved settings or preferences in an application.
Now that we’ve covered the basics of local storage, let’s practice saving and retrieving simple data types. Local storage is often used to store data that a user has entered, such as a name or a favorite color, and retrieve it later. In this section, we’ll explore saving basic data types like strings and numbers.
Storing a string is straightforward. Since local storage only accepts data in string format, we can directly save text data without any additional steps.
localStorage.setItem('greeting', 'Hello, welcome back!');
In this example, we store the string "Hello, welcome back!" with the key "greeting". This means that whenever the user returns to the page, we can retrieve this greeting message from local storage and display it.
To retrieve a saved string, we use the getItem method with the key we used to save it. If the key exists, getItem returns the saved value as a string.
let greeting = localStorage.getItem('greeting');
console.log(greeting); // Output: "Hello, welcome back!"
If the "greeting" key does not exist, getItem will return null. This is helpful for checking if data has been saved before trying to use it.
Although local storage requires values to be strings, we can still save numbers by converting them to strings during storage.
let visitCount = 5;
localStorage.setItem('visitCount', visitCount.toString());
Here, we’re saving a number (5) as a string by calling .toString() on it. If we need to store a number, converting it to a string is a simple way to ensure local storage can handle it.
When retrieving a number stored as a string, we can convert it back to a number with parseInt() or parseFloat() (depending on whether it’s an integer or decimal).
let visitCount = parseInt(localStorage.getItem('visitCount'), 10);
console.log(visitCount); // Output: 5
Using parseInt with a base of 10 (decimal) converts the string "5" back to the number 5.
Let’s bring everything together with a practical example that combines a saved message and visit count:
localStorage.setItem('welcomeMessage', 'Welcome back to our site!');
localStorage.setItem('visitCount', (1).toString());
let welcomeMessage = localStorage.getItem('welcomeMessage');
let visitCount = parseInt(localStorage.getItem('visitCount'), 10);
// Display the message
console.log(welcomeMessage); // Output: "Welcome back to our site!"
// Update the visit count and save it again
visitCount += 1;
localStorage.setItem('visitCount', visitCount.toString());
console.log(`You have visited ${visitCount} times.`);
In this example:
With these techniques, you can use local storage to save and retrieve simple data types in JavaScript, giving users a more personalized experience that persists across visits. In the next section, we’ll build on these basics to save and retrieve more complex data types like arrays and objects.
Local storage is versatile, but it stores data only as strings. When we need to store more complex data types, like arrays or objects, we can use JSON (JavaScript Object Notation) to convert these structures into strings. This way, we can save structured data that can be retrieved and restored to its original format.
To store arrays and objects in local storage, we first need to convert them into a JSON string using JSON.stringify(). This method transforms complex data into a format that local storage can handle.
let favoriteColors = ['blue', 'green', 'purple']; localStorage.setItem('favoriteColors', JSON.stringify(favoriteColors));
In this example, we use JSON.stringify(favoriteColors) to convert the array into a string format before saving it with the key "favoriteColors". This makes it easy to retrieve and work with later.
let userSettings = {
theme: 'dark',
fontSize: '16px',
notifications: true
};
localStorage.setItem('userSettings', JSON.stringify(userSettings));
Here, the object userSettings is converted to a JSON string, making it ready to be saved to local storage.
When we retrieve a JSON string from local storage, we need to convert it back to its original format (array or object) using JSON.parse(). This method takes the stored JSON string and parses it back into a JavaScript array or object.
let favoriteColors = JSON.parse(localStorage.getItem('favoriteColors'));
console.log(favoriteColors); // Output: ['blue', 'green', 'purple']
If the "favoriteColors" key exists, it will be parsed and converted back into an array. If it doesn’t exist, getItem will return null, which we can handle with a conditional check.
let userSettings = JSON.parse(localStorage.getItem('userSettings'));
console.log(userSettings);
// Output: { theme: 'dark', fontSize: '16px', notifications: true }
This code retrieves the JSON string associated with "userSettings" and parses it back into an object.
Let’s put this all together in a practical example that stores a user’s settings and retrieves them when they return to the page:
let userPreferences = {
language: 'English',
theme: 'light',
showWelcome: false
};
localStorage.setItem('userPreferences', JSON.stringify(userPreferences));
let userPreferences = JSON.parse(localStorage.getItem('userPreferences'));
// Check if the preferences exist before trying to use them
if (userPreferences) {
console.log(`Preferred language: ${userPreferences.language}`);
console.log(`Theme: ${userPreferences.theme}`);
console.log(`Show welcome message: ${userPreferences.showWelcome}`);
} else {
console.log('No preferences found. Setting defaults.');
}
This example retrieves the user’s preferences from local storage (if they exist) and displays them. If userPreferences doesn’t exist, we log a message indicating that no data was found.
When using JSON.parse(), it’s good to wrap it in a try...catch block. If data in local storage is corrupted or cannot be parsed, JSON.parse() will throw an error.
try {
let data = JSON.parse(localStorage.getItem('someKey'));
} catch (e) {
console.error('Failed to parse data:', e);
}
Always check for null after retrieving data. If a key does not exist in local storage, getItem returns null, so parsing null will cause errors.
Remember that local storage has a limit, typically around 5-10 MB, which may restrict the amount and type of data you can store.
Using JSON.stringify() and JSON.parse(), you can store and retrieve complex data types like arrays and objects in local storage. These techniques allow you to save more sophisticated user data, like preferences, settings, and lists, giving your applications a more personalized and persistent experience. In the next section, we’ll explore creating a project to apply these concepts and deepen your understanding of working with local storage.
Local storage provides a convenient way to store data on a user’s browser, but it comes with important security considerations and limitations. In this section, we’ll cover best practices and precautions to keep data secure and understand the limitations of local storage.
Local storage is accessible through JavaScript on the client side, meaning that data stored in it can potentially be accessed by other scripts running on the same page, including malicious ones. Here are some key security points to keep in mind:
Local storage has a few technical limitations that make it unsuitable for certain use cases. Understanding these limitations can help you design better data storage strategies.
Local storage is a helpful tool for saving non-sensitive data that needs to persist across sessions. However, it has several limitations and security concerns, including limited storage capacity, lack of encryption, and vulnerability to XSS attacks. For sensitive data or large-scale storage needs, consider using alternative storage options like secure cookies, server storage, or IndexedDB.
By following these guidelines, you can make informed decisions about when to use local storage and how to use it safely. In the next section, we’ll wrap up with best practices and practical examples to help reinforce these concepts.