DEV Community

Cover image for Copy by Value vs Reference
iAmGjert
iAmGjert

Posted on

Copy by Value vs Reference

Intro
There are two ways to pass a value to a variable in JavaScript and understanding how they operate is fundamental to your success at manipulating data in your code. In this short blog I will explain the differences between the two and provide examples along the way. Variables will either be passed a copy of the value of they're being assigned, or be passed a reference to the value they're being assigned.
sample variable

Copy by Value
When working with primitive data types (numbers, strings, Booleans, null, and undefined) your variables will be making a copy of the value they're being assigned and represent that specific copy of the value. Any changes to the original data will not effect the copy that was made and stored in the variable we've created. Vice versa, these values stored into our variable can be manipulated without any changes to the original data.

value copies

In the image above, b is being assigned the value stored in the a variable. Since the a variable is storing a primitive data type b is assigned a copy of that value. Any changes made to a later on will not effect b's value.
a === 1 //true b === 1 //true

a = undefined;
console.log(b); // prints 1, not effected by a being reassigned.
Enter fullscreen mode Exit fullscreen mode

Copy by Reference
When working with complex data types (Objects, arrays, functions) your variables will not make a copy of the value they're being assigned to, but instead will make a reference to that data. Any manipulation of our variable will effect the original data since our variable is just a reference to the original data. Similarly, any changes to the original data will effect our variable as well.

let a = {
   name: 'Object',
   color: 'blue'
}
let b = a;
Enter fullscreen mode Exit fullscreen mode

In the code above, the a variable has been assigned to an object with two properties. Just under that, we've assigned the b variable to the a variable. When the b variable is assigned here, it will be assigned a reference to the same object the a variable is already assigned to. Any changes to the b variable will effect the original data stored in the a variable.
b.color = 'orange'
Since both variables point to the same object, the color of the object both variables point to will be assigned to 'orange'.

console.log(a); // prints {name: 'Object, color: 'orange'} 
console.log(b); // prints {name: 'Object, color: 'orange'}
Enter fullscreen mode Exit fullscreen mode

by reference

In Summary
coffee cupsIt's important to know whether the data you're working with is a copy or a reference. If you're working with a copy it's less detrimental to the overall program as your changes are localized to that copy of the data. When working with a reference your changes effect the overall data and can produce unwanted changes later in your code if not caught.

Top comments (14)

Collapse
 
parenttobias profile image
Toby Parent • Edited

The issue with the whole "pass by value" vs "pass by reference" thing is, javascript doesn't really do either. Well it does both. Well it does...

Javascript is consistent, both primitives and non-primitives work the same way. A string is passed the same way as an object, in large part. But the concepts of value or reference is fuzzy here, because any references are implicit, not explicit. We don't have pointers, so we aren't sharing a reference - but it seems we do, as arrays and objects are mutable from either side.

I think the best description I've seen for javascript's way of passing is Pass by share. When we pass something into a function, be it primitive or not, we are sharing the reference to that thing. We can't act on the reference, we can only follow it. In the case of primitive data types the value we reach is immutable, so any transformation becomes a new thing. But with non-primitive types, where mutation is possible, a shared reference becomes a little more problematic.

I've always seen the "Is javascript pass by reference or pass by value?" to be a trick question, for which there is no clean answer. It's the kind of a question, in an interview, intended to be wrong.

Edit for completeness: When I mentioned above "in large part*, it's because, internally, javascript does funky stuff with smallInt values, from what I've read. Rather than the variable referencing a lookup table, which referrences memory locations, which reference values? From what I've read, smallInt values are the only ones stored directly in the lookup table, and thus the only ones pass by value. What that means? Absolutely no idea. Still trying to test that, and see if it's relevant.

Collapse
 
aminmansuri profile image
hidden_dude

The true way to know if you're passing by reference in a language is this:

func f(ref val) {
val = newVal;
}

x = something
f(x)

If x is now equal to newVal then your language supports passing by reference (ex: in Pascal this works with var, or in C++ & notation). If x is still equal to "something" then I'm afraid you don't have true pass by reference.

Collapse
 
guillep2k profile image
Guillermo Prandi

That's a different discussion. The article is about assignments, not function calling.

Collapse
 
parenttobias profile image
Toby Parent

And that's why I suggest a different verb, pass by share. We are sharing that reference in an assignment to another variable, rather than passing the value itself. However the reference is tied to the immutable value, and not to the variable.

Javascript is weird, but once you grok, it actually makes a lot of sense.

Collapse
 
jkhaui profile image
Jordy Lee

Nice article. For completeness’ sake and clarity, you might want to add ‘Symbol’ and ‘BigInt’ for the full list of JS primitive types.

Might also wanna let readers know that arrays and functions in JS are technically objects too :)

Collapse
 
sarveshprajapati profile image
Sarvesh Prajapati

Great article though...
Would be better to discuss a bit about heap. Either way... great content

Collapse
 
danwalsh profile image
Dan Walsh

Great read! 👏

It's worth mentioning that if you're intending to make a copy of a non-primitive, you can do so using the spread operator:

/**
 * Objects
 */
const myObj = {name: "Fred", age: 10};
const copiedObj = {...myObj};
copiedObj.name = "Dan";
console.log(myObj, copiedObj);
// > {name: "Fred", age: 10}, {name: "Dan", age: 10}

/**
 * Arrays
 */
const myArr = ["Fred", 10];
const copiedArr = [... myArr];
copiedArr[0] = "Dan";
console.log(myArr, copiedArr);
// > ["Fred", 10], ["Dan", 10]
Enter fullscreen mode Exit fullscreen mode

I find it particularly useful when making changes to the state object in my React useReducer() logic.

Collapse
 
marcio199226 profile image
oskar • Edited

Watch out that objects copied by destructuring it will be a shallow copy so any nested objects will still link to their "reference"

const myObj = {name: "Fred", age: 10, nested: { surname: "Flinstone" }};
const copiedObj = {...myObj};
copiedObj.name = "Dan";
copiedObj.nested.surname = "Qwerty";
console.log(myObj, copiedObj);
Enter fullscreen mode Exit fullscreen mode

The same happens to arrays as well

Collapse
 
danwalsh profile image
Dan Walsh

Great point! It clearly illustrates that you need to pick the method for your specific needs: by reference, shallow copy and deep copy. Each has its pros, cons and use cases.

Collapse
 
guillep2k profile image
Guillermo Prandi

One could argue that every variable holds a reference, at least in abstraction. Using let a = 1 doesn't contradict this, because one can say it's the object 1 that's being assigned. This pseudo object has no properties and can not be manipulated, but can be assigned to other variables, just like any bonafide object. If we then say a = 2, we'd be changing the referencea is pointing to, rather than changing the actual number. I know this is entirely semantics, and that the actual implementation does classify values as different from references internally, but making that distinction while learning the language seems unnecessary. I hope this makes sense.

Collapse
 
jawwad profile image
Jawwad Al Sabbir

This is very informative in a short lengh.

Collapse
 
ash_bergs profile image
Ash

I like this add-on! I know this caveat to strings has tripped me up more than once.

Collapse
 
omarpervez profile image
Omar Pervez

Excellent blog. Thank you for sharing your ideas with us😊

Collapse
 
sarveshprajapati profile image
Sarvesh Prajapati

exactly