Skip to content

Instantly share code, notes, and snippets.

@idiotWu
Last active October 7, 2022 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save idiotWu/b833099e9b9cca43cb7ff2f7e37b364c to your computer and use it in GitHub Desktop.
Save idiotWu/b833099e9b9cca43cb7ff2f7e37b364c to your computer and use it in GitHub Desktop.
undo/redo with prototype chains
class HistoryManager {
constructor(initialState) {
this.state = { ...initialState };
this.history = [initialState];
this.index = 0;
}
push(changes) {
this.state = Object.create(this.state, Object.getOwnPropertyDescriptors(changes));
this.history.length = this.index + 1; // discard further redos
this.history.push(this.state);
this.index++;
return this.state;
}
undo() {
if (this.index === 0) {
return;
}
this.index--;
this.state = this.history[this.index];
return this.state;
}
redo() {
if (this.index === this.history.length - 1) {
return;
}
this.index++;
this.state = this.history[this.index];
return this.state;
}
}
// test
const hist = new HistoryManager({ a: 0 });
hist.push({ a: 1 });
console.assert(hist.state.a === 1);
hist.push({ a: 2 });
hist.push({ a: 3 });
console.assert(hist.state.a === 3);
hist.undo();
hist.undo();
console.assert(hist.state.a === 1);
hist.redo();
console.assert(hist.state.a === 2);
hist.push({ a: Infinity });
console.assert(hist.state.a === Infinity);
hist.redo();
console.assert(hist.state.a === Infinity);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment