</>
Skip to content
JavaScript lessons (57/64)

JavaScript — History

The session history

Each tab keeps its own navigation stack:

history.back();       // ← like the Back button
history.forward();    // →
history.go(-2);       // jump two entries back

history.length;       // how deep this tab's stack is (no URLs exposed!)

Scripts can only manipulate their own tab's session history — reading the user's full browsing history is off-limits by design.

pushState — URL changes without reloads

The foundation of every single-page app:

history.pushState(
    { page: "about" },     // state object (yours to define)
    "",                    // title (mostly ignored)
    "/about"               // visible URL — same-origin only!
);

location.pathname;   // "/about" — but NO network request happened

The state travels with that entry:

history.state;         // { page: "about" }

popstate — reacting to Back/Forward

window.addEventListener("popstate", event => {
    console.log(event.state);          // state of the NEW current entry
    render(location.pathname);         // re-render for the URL
});

Fires on Back/Forward/go() — not on your own pushState calls (call render yourself there).

pushState vs replaceState

history.pushState(state, "", url);     // ADDS a step (Back returns here)
history.replaceState(state, "", url);  // OVERWRITES current entry

replaceState suits: fixing a canonical URL after filters change, cleaning tracking params — anywhere Back shouldn't replay a meaningless intermediate state.

Minimal SPA router in ~10 lines

function navigate(path) {
    history.pushState({}, "", path);
    render(path);
}

window.addEventListener("popstate", () => render(location.pathname));

document.querySelectorAll("a[data-link]").forEach(a =>
    a.addEventListener("click", e => {
        e.preventDefault();
        navigate(a.getAttribute("href"));
    })
);

Your app now owns rendering per URL.

Scroll restoration

history.scrollRestoration;   // "auto" (browser tries) | "manual"
history.scrollRestoration = "manual";   // you control scroll on navigation

Gotchas

  1. pushState does NOT fetch anything — you must render the content; servers must also handle direct visits to SPA routes
  2. Same-origin URLs only — it's not a redirect tool
  3. State objects are serialized (structured clone) — functions need not apply

Mini Practice

  1. Walk back/forward programmatically; log history.length at each stop.
  2. pushState three routes with distinct state objects.
  3. Render different content per route via popstate + pathname.
  4. Use replaceState to strip a ?ref=spam parameter.
  5. Set scrollRestoration manual; observe Back behavior change.

Next: navigator →

Related Topics

Frequently Asked Questions about History

What is History in JavaScript?

History is a fundamental concept in JavaScript. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn History?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn History.

Why is History important in JavaScript?

History is essential for JavaScript development. Understanding this concept will help you write better code and solve real-world problems more effectively.