Week 3
3.9 JavaScript and the Browser
Week 3
3.9 JavaScript and the Browser
In this section, we'll explore how JavaScript interacts with the browser, enhancing performance, managing storage, and optimizing event handling.
Modern web applications often need to store user data locally. JavaScript provides two main options for this:
Feature LocalStorage SessionStorage
Storage Limit ~10MB ~5MB
Persistence Permanent (until cleared) Temporary (deleted when tab closes)
Access Scope Available across all pages of Available only in the same tab/session
the same origin
The localStorage API allows you to store key-value pairs in the browser that persist even after the page is refreshed.
Saving Data
localStorage.setItem("username", "Alice");
Retrieving Data
let user = localStorage.getItem("username");
console.log(user); // Output: Alice
Removing Data
localStorage.removeItem("username");
Clearing All Data
localStorage.clear();
Similar to localStorage, but the data disappears when the user closes the tab.
Saving Data
sessionStorage.setItem("sessionID", "ABC123");
Retrieving Data
let session = sessionStorage.getItem("sessionID");
console.log(session); // Output: ABC123
Removing Data
sessionStorage.removeItem("sessionID");
Use Case Example: Remembering Form Input
document.querySelector("input").addEventListener("input", (event) => {
sessionStorage.setItem("formData", event.target.value);
});
If the user accidentally refreshes the page, we can restore the input:
document.querySelector("input").value = sessionStorage.getItem("formData") || "";
Normally, JavaScript runs in a single thread. If your script is performing a heavy calculation, it can freeze the page.
Web Workers let JavaScript run tasks in the background, without affecting the main UI thread.
1, Create a new JavaScript file (worker.js)
self.onmessage = function (event) {
let result = event.data * 2; // Simulating heavy computation
self.postMessage(result); // Send result back to main thread
};
2, Use the Worker in the Main Script
let worker = new Worker("worker.js");
worker.postMessage(10); // Send data to worker
worker.onmessage = function (event) {
console.log("Result from worker:", event.data); // Output: 20
};
Handling large computations (e.g., image processing, data sorting)
Keeping UI responsive when fetching data
Running real-time updates without blocking interactions
Imagine you have 100 buttons inside a <div>, and you add an event listener to each one:
document.querySelectorAll(".btn").forEach(button => {
button.addEventListener("click", () => alert("Clicked!"));
});
BAD IDEA! This creates 100 separate event listeners, consuming memory and slowing performance.
Instead of adding a listener to each element, attach one listener to a parent element and use event bubbling to detect clicks.
document.querySelector("#parentDiv").addEventListener("click", function (event) {
if (event.target.classList.contains("btn")) {
alert("Button clicked: " + event.target.textContent);
}
});
Why is this better?
Only one event listener instead of 100+
Works for dynamically added buttons
1, Avoid Layout Thrashing
Bad:
for (let i = 0; i < 1000; i++) {
let element = document.createElement("div");
element.textContent = "Item " + i;
document.body.appendChild(element); // Multiple reflows!
}
Better Approach (Use Document Fragment)
let fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
let element = document.createElement("div");
element.textContent = "Item " + i;
fragment.appendChild(element);
}
document.body.appendChild(fragment); // Single reflow!
2, Use requestAnimationFrame() for Smooth Animations
function animate() {
// Update animation
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
3, Debounce & Throttle Expensive Events (e.g., Scroll, Resize, Input)
Without optimization: Every scroll event triggers code hundreds of times per second!
window.addEventListener("scroll", () => {
console.log("Scrolling...");
});
Throttle: Limit the event execution rate
function throttle(func, limit) {
let inThrottle;
return function () {
if (!inThrottle) {
func.apply(this, arguments);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
window.addEventListener("scroll", throttle(() => console.log("Scrolling..."), 200));
1️⃣ Create a to-do list app using localStorage to save tasks even after refreshing the page.
2️⃣ Implement Web Workers to calculate factorials without freezing the UI.
3️⃣ Use event delegation to handle clicks on a dynamic list of items.
Master these techniques, and your JavaScript apps will be faster, smarter, and more efficient!
Next Up: Object-Oriented Programming (OOP) in JavaScript.