DEV Community

Cover image for How to assign two Variables to the same Object
Aaron George
Aaron George

Posted on • Edited on

How to assign two Variables to the same Object

Let's say we have an object and want to assign two different variables to it, we could do the following:

const vala = 100
const valb = { life: 42 }

let a, b
a = b = { propa: vala, propb: valb }

The keen eye will have noticed one fatal flaw with this code: Changing a.propa will also change b.propa.
This is due to a and b both referencing the same object, it might be easier to notice if we wrote it like this instead:

const vala = 100
const valb = { life: 42 }
const objectToClone = { propa: vala, propb: valb }

let a, b
a = b = objectToClone

The last line says we want a to equal b and b to equal objectToClone, so both a and b reference the same object. This might be fine for your purposes, but it's quite likely undesired behaviour.
Let's go over a few solutions to this problem:

const vala = 100
const valb = { life: 42 }

let a = { propa: vala, propb: valb }
let b = { propa: vala, propb: valb }

This solution works as you might expect. You could change a.propa and b.propa would be untouched; indeed a and b reference different objects, of the same values.

However if you answer "yes" to the following question: Do propa or propb reference an object?, then you face another potential issue: Objects in JavaScript are passed by reference, not by value.

What does this mean? I'll point you to this article to explain, but once you know what the difference is, continue below

So now you know what passing by reference means, you'll notice in our example, valb is an object. Our issue now is that if any changes happen to valb, they will be reflected in a.propb and b.propb.

So how do we get around this issue?

const vala = 100
const valb = { life: 42 }

let a = JSON.parse(JSON.stringify({ propa: vala, propb: valb }))
let b = JSON.parse(JSON.stringify({ propa: vala, propb: valb }))

We have now made it so any changes to a.propb and b.propb don't affect each other, as they now reference different objects, with copies of the same values. This is thanks to the power of JSON.parse and JSON.stringify, I'll point you to this post for a run-down

Now this seems like an awful lot of code, just to assign two variables to different copy of the same object. So let's do better!

First we have the benefits of shorthand object property declarations in ES6:

const vala = 100
const valb = { life: 42 }

let a = JSON.parse(JSON.stringify({ vala, valb }))
let b = JSON.parse(JSON.stringify({ vala, valb }))

This comes with the trade-off of having to now get the values of a.propa, a.propb, b.propa and b.propb with a.vala, a.valb, b.vala and b.valb instead.

If you wanted too, you could change the vala and valb declarations to propa and propb, but that isn't semantic, so please don't do that!

Next we can do the following:

const vala = 100
const valb = { life: 42 }

let a, b
a = JSON.parse(JSON.stringify({ vala, valb })), b = JSON.parse(JSON.stringify(a))

Which we could collapse like so:

const vala = 100
const valb = { life: 42 }

let a, b; a = JSON.parse(JSON.stringify({ vala, valb })), b = JSON.parse(JSON.stringify(a))

If you wanted to take it one step further, you can create an VSCode snippet like so:

{
    "Two reference object copy": {
        "prefix": "troc",
        "body": ["let ${1:a}, ${2:b}; ${1:a} = JSON.parse(JSON.stringify(${3:obj})), ${2:b} = JSON.parse(JSON.stringify(${1:a}))", "${0}"],
        "description": "Declares two references to a copy of an object"
    }
}

This will allow you to type troc and type the name of the first reference declaration, hit tab, type the second, hit tab and finally type the object to clone for each reference
I hope this helps anyone who has come across this problem and wanted a solution

Note: I am aware of the potential performance impacts of using the JSON methods. If you wanted to you could use _.cloneDeep by Lodash to make this even more succinct.

However with most higher programming pursuits, less code usually involves higher impact to performance.

Top comments (0)