Dealing With Values by Reference

(a.k.a cloning)

@stuartrunyan

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"}]}
					

A few things to consider.

  1. When dealing with state, think about where it came from and if it's a reference.
  2. Even when cloning understand your data structure and if it needs a deep clone.
  3. When possible prefer Immutable data structures. This is something you have to enforce in your code.

If interested in understanding values by reference and cloning objects you should read up on a few topics.

  • Cloning / Shallow copy
  • Deep cloning
  • Immutable data structures

Your Friend


_.clone()
					

Questions?