DEV Community

Anthony Frehner
Anthony Frehner

Posted on • Edited on

Interactions with the history stack

JS Trivia time: given the following code, what is logged?

window.history.pushState(null, null, "/temp1");
window.history.pushState(null, null, "/temp2");
window.history.pushState(null, null, "/temp3");

console.log("before go", window.history.length);
window.history.go(-3);

console.log("after go", window.history.length);
window.history.pushState(null, null, "/temp4");

console.log("after go after pushState", window.history.length);
Enter fullscreen mode Exit fullscreen mode

Answer (click to see)
before go 4
after go 4
after go after pushState 2
Enter fullscreen mode Exit fullscreen mode


Followup question!

window.history.pushState(null, null, "/temp1");
window.history.pushState(null, null, "/temp2");
window.history.pushState(null, null, "/temp3");

console.log("before go", window.history.length);
window.history.go(-3);

console.log("after go", window.history.length);
window.history.replaceState(null, null, "/temp4");

console.log("after go after replaceState", window.history.length);
Enter fullscreen mode Exit fullscreen mode

Answer (click to see)
before go 4
after go 4
after go after replaceState 4
Enter fullscreen mode Exit fullscreen mode


What's going on?

The history stack allows you to navigate through it, and it will maintain the stack as it was through your navigation. However, when you push onto the stack, you erase any future navigations from your current location in the stack.

A simplified demonstration:

window.history.pushState(null, null, "/temp1");
// history.stack looks like ['', '/temp1']
// current entry is '/temp1'

window.history.pushState(null, null, "/temp2");
// history.stack looks like ['', '/temp1', '/temp2']
// current entry is '/temp2'

window.history.pushState(null, null, "/temp3");
// history.stack looks like ['', '/temp1', '/temp2', '/temp3']
// current entry is '/temp3'

console.log("before go", window.history.length);
// before go 4

window.history.go(-3);
// history.stack looks like ['', '/temp1', '/temp2', '/temp3']
// current entry is ''

console.log("after go", window.history.length);
// after go 4

window.history.pushState(null, null, "/temp4");
// history.stack looks like ['', '/temp4']
// current entry is '/temp4'

console.log("after go after pushState", window.history.length);
// after go after pushState 2
Enter fullscreen mode Exit fullscreen mode

and if we were only to change the pushState call above with replaceState, here's what it would look like:

window.history.replaceState(null, null, "/temp4");
// history.stack looks like ['/temp4', '/temp1', '/temp2', '/temp3']
// current entry is '/temp4'
Enter fullscreen mode Exit fullscreen mode

Spec talk

Here's a link to the WHATWG HTML spec for history update steps.

The key thing to pay attention to here is step 2:

2 If isPush is true, then:

2.1 Remove all the entries in browsingContext's session history after the current entry. If the current entry is the last entry in the session history, then no entries are removed.

isPush is true for pushState and false for replaceState, which can be found here for pushState and here for replaceState - paying attention to the last words in those sentences.

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay