let doFn, undoFn; {const newStroke = currentStroke; doFn = ()=>strokes.push(newStroke); undoFn = ()=>strokes.pop();}In the code above, `newStroke` just makes a reference to `currentStroke`. Nothing is changed by creating a `const newStroke` and pushing it to the array. You're just pushing a reference to the original. In the OP's example, `currentStroke` is something that gets modified. If you used the code above, as soon as you modify `currentStroke`, every reference in the `strokes` array will change. The fact that you used `let` instead of `var` in the loop means you are creating a new constant, but that constant isn't preserving a snapshot of `currentStroke` unless you explicitly make it a new object. Otherwise it's just a reference. You need to deep-clone it in the undo function in order to preserve its previous state. Something like:
`let previousStroke = {a:currentStroke.a,b:currentStroke.b}` where `a` and `b` are primitives that are copied, not objects that are referenced, before you change `currentStroke`. If you did it manually, you'd have to keep keep recursively checking `a` and `b` all the way down to their primitives, and rebuild the object.
An easy way of doing this for objects without functions or classes in them is just `const previousStroke = JSON.parse(JSON.stringify(currentStroke));` but usually I've had to write custom re-initializers if for example `previousStroke.a` was a class instance.
Not true. If you look carefully you will see the `const` and everything after it is wrapped in curly braces, and those braces create a block...
> Traditionally (before ES6)... blocks with curly braces do not create scopes... [but] blocks are finally treated as scopes in ES6, but only if you declare variables with let or const. — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
So the curly braces with the use of const/let creates a new lexical scope, hence solving the issue. You can test it in the browser console to confirm;
var stack=[], cmd="";
cmd="success"; stack.push(()=>cmd);
cmd="fail"; stack.push(()=>cmd);
stack[0](); /* returns "fail" */
var stack=[], cmd="";
cmd="success"; {const c=cmd; stack.push(()=>c);}
cmd="fail"; {const c=cmd; stack.push(()=>c);}
stack[0](); /* returns "success" */
It's probably not a good idea to do it this way, because it's easily "overlooked". I would probably use a class or factory-function if I had the need.