How to Make a Undo/Redo Function

I want to add a undo/redo function in my script. I have looked around and see some suggestions, most of them recommended to use command pattern.

The function must work over one page - after a reload of the page the function must able to redo/undo the last things.

I don't know how command pattern works, I think about to create a object, to store the a name of the function, the old and the new value - but I'm not sure if this is a efficient way to do this or not.

Maybe somebody could give me a small example how the code for a undo/redo function should look.

1 Answer

There's 2 common ways of implementing undo/redo:

  • The Memento Pattern, where you capture the whole current state. It's easy to implement, but memory-inefficient since you need to store similar copies of the whole state.
  • The Command Pattern, where you capture commands/actions that affect the state (the current action and it's inverse action). Harder to implement since for for each undoable action in your application you must explicitly code it's inverse action, but it's far more memory-efficient since you only store the actions that affect the state.

The Memento Pattern

Before an action is applied, you take a snapshot of the current state and save it into an array. That snapshot is the Memento.

If the user wants to undo, you simply pop the last memento and apply it. The program returns to the state it was before the last action was applied.

This pattern is memory intensive; each memento is relatively large since it captures the whole current state.

But it's also the easiest to implement since you don't need to explicitly code all cases and their inverse actions that you need to in the Command Pattern (see below).

const mementos = []
const input = document.querySelector('input')

function saveMemento() {
  mementos.push(input.value)
}

function undo() {
  const lastMemento = mementos.pop()
   
  input.value = lastMemento ? lastMemento : input.value
}
<h4> Type some characters and hit Undo </h4>
<input onkeydown="saveMemento()" value="Hello World"/>
<button onclick="undo()">Undo</button>
Chloe Bennett

Chloe Bennett

Culture, Media & Entertainment Columnist

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.