Navigation and History in JavaScript
Introduction
Browsers track where users go with the History API and location object. Single-page apps (SPAs) change URLs without full page reloads using history.pushState. This chapter covers reading URLs, programmatic navigation, and listening for back/forward buttons.
Prerequisites
location Object
// Current page URL parts (in browser console)
console.log(location.href);
console.log(location.pathname);
console.log(location.search);
console.log(location.hash);Navigate away (full reload):
// Assigning href reloads page
// location.href = "https://example.com/docs";Query String with URLSearchParams
// Parse ?q=node&page=2
const params = new URLSearchParams(location.search);
console.log(params.get("q"));
console.log(params.get("page"));
params.set("page", "3");
const nextSearch = params.toString();
console.log(`${location.pathname}?${nextSearch}`);history.pushState — SPA Routes
Framework routers (React Router, Vue Router) wrap the same History API.
history.replaceState
Like pushState but replaces current entry—good for redirects without extra back-stack entries.
navigator Snippets (Related)
// Language and online status — not navigation but common with locale
console.log(navigator.language);
console.log(navigator.onLine);
window.addEventListener("online", () => console.log("back online"));
window.addEventListener("offline", () => console.log("offline"));Geolocation is a separate permission-gated API (navigator.geolocation)—use only with user consent.
Mini Example: Hash-Based Tab Switch
Hash routing avoids server config for simple demos; path routing needs server fallback to index.html.
FAQ
pushState vs location.hash?
pushState gives clean URLs (/app/settings); hashes (#/settings) are easier for static hosting without rewrite rules.
Open links in new tab?
<a target="_blank" rel="noopener noreferrer"> for external URLs.
SSR frameworks?
Server must know routes too—client-only pushState is not enough alone.