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 UTC
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
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"}]}
If interested in understanding values by reference and cloning objects you should read up on a few topics.
_.clone()