On Github shrunyan / sdjs-cloning
I constantly forget that in JavaScript values are passed by reference.
This has caused me many pains when dealing with state mutations.
One of my latest issue with this was in momentjs.
let moment = require('moment') let time = moment() console.log(time.format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 11:17:32 am" console.log(time.utc().format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 6:17:32 pm" console.log(time.format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 6:17:32 pm" // WAT?
Read the Docs. I mean REALLY read the docs!
Sets a flag on the original moment to internally use Date#getUTC* and Date#setUTC* instead of Date#get* and Date#set*. — Moment UTCtotally my fault
Momentjs is simply the latest example of this problem for me.
I used to deal with this a lot in Backbonejs with complex data structures in models.
How can we avoid this specific issue?
Clone the, moment, object.
let moment = require('moment') let time = moment() console.log(time.format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 11:17:32 am" console.log(time.clone().utc().format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 6:17:32 pm" console.log(time.format("dddd, MMMM Do YYYY, h:mm:ss a")) // "Tuesday, October 6th 2015, 11:17:32 am"
Great! But how do I do this outside of moment?
Check your preferred lib it most likely has a clone() function.
$.clone() _.clone()
Otherwise, I would recommend lodash.clone
lodash is going to be a good framework agnostic solution.
Not all copying/cloning is equal
let me = { name: 'Stuart', movies: [{ title: 'Star Wars', fav: true },{ title: 'Mad Max 2' },{ title: 'Monty Python' }] } let miniMe = Object.assign({}, me) miniMe.name = 'Mini Stuart' miniMe.movies[0].fav = false console.log(me) // {"name":"Stuart","movies":[{"title":"Star Wars","fav":false},{"title":"Mad Max 2"},{"title":"Monty Python"}]} console.log(miniMe) // {"name":"Mini Stuart","movies":[{"title":"Star Wars","fav":false},{"title":"Mad Max 2"},{"title":"Monty Python"}]}
An illustration of this problem with a complex data structure.
Explain shallow vs deep clone/copy
Alot of times we inherit codebases. Make sure you wrap your head around the codes state.
Complex data structures need deep clones otherwise you introduce the same mutation issue but in a more convoluted way.
JavaScript is not inherently immutable. It's a pattern you must apply to your code. This is out of scope of the talk.
If interested in understanding values by reference and cloning objects you should read up on a few topics.
Can not stress immutable enough. This is what the industry is pushing towards. Espcially with one-way data flows.
_.clone()
in summary
I'd encourage you not to write this logic on your own. The community testing factor of oss solutions can't be underestimated.